Friday, September 7, 2012

Manipulating page styles with the new Greasemonkey

This article assumes that the reader knows some JavaScript and a fair share of CSS, and how to create userscripts for Greasemonkey.

The argument for using Greasemnkey is that it allows for a more straightforward implementation of user-created styles, which don't require remote storage, such as userscripts.org.


Well, as of recently, it became impossible to manipulate styles on pages with modern versions of Greasemonkey running within Firefox and SeaMonkey.

I suppose this might have happened during the transition from Firefox 12 to some newer version. Oddly, the version of SeaMonkey has always remained the same, so this should somehow have ruled out that issue. Then I began thinking of NoScript — which is about the only extension maintained well for both SeaMonkey and Firefox, and updatd accordingly — but I'm not going to point any fingers, just because I don't know what the real cause is.

So, the situation happened to me using SeaMonkey 2.5 (which I am not using often, though planning to upgrade one day) with Greasemonkey 0.9.13.1, and in Firefox 15 with about the latest modern releases of Greasemonkey (0.9.22—1.x).
Greasemonkey is officially available only for Firefox, but since SeaMonkey 2.x is not supported by many extension developers, then Philip Chee decided to modify ostensibly free software extensions originally made for Firefox to then post them at xsidebar.mozdev.org for other SeaMonkey users. Some of the extensions are modified by request of other users. So the most recent Greasemonkey version for SeaMonkey 2.3 or newer is 0.9.13.1, which is modern, but by no means the newest fare.
If you think usescripts somehow stopped working, then this is not quite so. Compared to older implementations, Greasemonkey has just evolved and so have ways to manipulate styles with usescripts. IMHO.

The traditional, or classic, way of inserting lines of style code in a Greasemonkey userscript was something like this:
document.styleSheets[0].insertRule('DIV[class=pagecontent] {width:auto !important; max-width:1014px !important;}', 0);

^ Nevermind !important, which was meant to override existing online style rules. Writing declarations with [square brackets] is also clunkier, but more reliable.

Now, there are a few things about the metadata block to remember when composing a userscript: @namespace and @grant.
  • @namespace does require that something is written for it. For the example I had, I wrote random, and it works for a test script, but the string can't be empty and has to be meaningful, per instructions given in the link.
  • With the second, I set @grant to none.
    T., 29.01.2013. update:
    @grant is a new(ish) security measure to limit API access of a script. With this it's possible to grant none (no API access) and grant GM_*, where script lines starting with GM_* are allowed. One such example is the simplified way of modifying CSS styles through GM_addStyle. To allow GM_addStyle, set

    @grant GM_addStyle

    In conclusion, this is what I think is something that I overlooked when initially writing the blog post herein.
Interestingly, I discovered that @include strings can be equipped with wildcards. This could be an age-old feature, but this saved me a bit of effort in writing userscript code:
// @include       *.wikipedia.org/wiki/*
• By not including http:// and https:// protocols, the userscript should work for domains under both;
• The asterisk * before the primary domain (separated by a dot) allows for inclusion of subdomains. Anyhoo, the new way to insert custom style blocks is this:
GM_addStyle("DIV.pagecontent {width:auto !important; max-width:1014px !important;}")
Works for me.

No comments: