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.
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. |
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:
Here, I describe some common "advanced" user script techniques.
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()
.
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.
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.