User Scripts

User scripts are third-party JavaScript files that run in existing webpages. They usually customize the L&F or add new functionality.

For example, we watch videos on YouTube, but we cannot save them. A user script can expose the video links and allow us to save them easily.

User scripts can be very powerful, but are also very dangerous. Remember, it is a third-party script that runs in the context of the webpage: it has full access to that webpage! It is advisable to at least glance through the script before installing it to make sure it looks harmless.

Browser support

The biggest stumbling block is spotty browser support. In many cases, the user has to install an extension first. It is not possible to detect if the extension is present.

IE Not supported. There are extensions for IE 7, but not IE 8 and 9.
Firefox Need to install Greasemonkey first. After that, click on or drag-n-drop any .user.js file.
Chrome Supported natively since version 4 (now version 13). Just click on or drag-n-drop any .user.js file.
Safari Supported on Mac with GreaseKit extension. Not supported on Windows.
Opera Supported since version 8 (now 11.50). Need to configure the user script folder. After that, save the user scripts there.

Challenges

User script is just plain JavaScript, so if you know JavaScript, you can write a user script. It is best to hop over to the de facto user script repository userscripts.org and look at the scripts; most of them are just one page long.

However, there are additional challenges:

Techniques

Here, I describe some common "advanced" user script techniques.

Adding styles

It is possible to insert a bunch of classes as a <style> block.

var head = document.getElementsByTagName("head") [0];
var style = document.createElement("style");
style.setAtribute("type", "text/css");
head.appendChild(style);
style.appendChild(document.createTextNode(...));

There is no need to use GM_addStyle().

Including another script

It is possible to include another script. This can be used to load jQuery, for example.

var script = document.createElement("script");
script.type = "text/javascript";
script.src  = "http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js";
document.body.appendChild(script);

Of course, we need to make sure the script is loaded before we use it — typically by polling for it.

This is much less efficient than using the @require meta-tag. However, this tag is only supported by Greasemonkey.

Checking for updated scripts

The recommended way is to use the @require meta-tag that points to a server-side script-checker script. However, the meta-tag only works in Greasemonkey.

We need to fallback to an old-fashion approach for this to work in all browsers. The simplest is to use JSONP, because it is the only cross-origin request that is guaranteed to work. (Only Greasemonkey allows cross-origin GM_xmlhttpRequest().)

JSONP means we load another JavaScript scipt using <script> whose sole purpose is to invoke a callback function with the latest version number. This allows the script to prompt the user if needed.

It is not necessary to check for updates all the time. The highest recommended checking frequency is once per day, although I prefer 3-7 days. This means we need to store the last check timestamp somewhere. Cookies are typically used, but localStorage can be used instead.