Over the past couple of weeks I have had to work closely with the custom scripts management system for Mozilla products -
GreaseMonkey . And since I myself have appointed the administrator of the blog of the same name, it means to write an introduction to the question - my sacred duty.
Introduction
')
GreaseMonkey (hereinafter GM) is a system for managing custom scripts for Mozilla products. In my article I will talk about the browser of this company, about Firefox further (FF). Also in some places I will touch on its competitors, namely Opera, Safari and of course Internet Explorer (hereafter IE).
User Script (User Script) - a script written in JavaScript (hereinafter referred to as JS), installed by the user in the browser and executed when web pages are loaded. Used to change their design (in the broad sense of the word).
Simply put, using custom scripts, you can add / remove / modify elements of a web page, change their behavior, improve User Experience.
Installation
GM is easily installed as an extension for FF from
the add-ons site . GM also has an
official website where you can find a lot of useful information.
After installing and restarting the FF icon will appear:

And this means that you can install custom scripts.
The largest
repository of user scripts is
userscripts.org . Installation is very simple. GreaseMonkey just intercepts the response to the request of the JS-file, and if it has a special header (I will tell about it below), it calls the installation dialog:

Overview
You can manage GM and installed scripts through the context menu, which is invoked by right clicking on the monkey face:

The top of the menu displays a list of scripts active for this page. Any script can be disabled by removing the check mark.
With
the GM
API you can expand this menu. All actions registered via
GM_registerMenuCommand will appear in the "Script Commands" submenu.
I will skip the “New Script” menu item, as I am sure that it is more convenient to make the script in the editor, including editing the meta-information. In any case, I hope that mastering this master will not cause readers problems.
Script Management invokes the following window:

In this window, you can customize any installed custom script yourself. To do this, select it in the left list. You can add remove URL masks for which this script will be loaded or NOT loaded (classic Allow / Deny), enable / disable / delete the script and, most importantly for the developer, edit it live.
To edit the script, click the "Edit" button. For the first time, GM will ask for an editor. In the following will automatically open a working copy of the script in the selected editor.
On this, the GM tour is considered complete and you can go directly to the subtleties of developing custom scripts.
Custom scripts
GM scripts are practically nothing (some of the features, I will discuss in the next section) are no different from ordinary JS scripts, so no special knowledge is needed for writing. But in order for GM to recognize the script as custom, you need to add a special header:
// ==UserScript==
// @name Weborama Inline Player
// @namespace tbms.ru/weborama/inline
// @description Includes weborama inline player
// @author Konstantin Shvydky, Nick Mitin
// @include *
// @exclude file://*
// ==/UserScript==
/*
This code is licenced under the GPL
www.fsf.org/licensing/licenses/gpl.html
*/
With name, author, description everything is clear, we must dwell on the remaining parameters
namespace - any URI (this is not a link, but an analogue of HTML namespace). You can read this parameter as a unique script identifier.
include - mask for pages that will activate this script. There may be several directives.
@exclude - mask for pages that will NOT activate this script. There may be several directives.
It is also good practice to indicate the license under which the script itself is distributed. This can be done below the metadata.
* About
metadata on greasespot.net.
The second prerequisite is the end of the file name. It must end with ".user.js", otherwise GM will not recognize the script.
The launch of the script for GM is performed in the order of priority when the
DOMContentLoaded event
occurs at the processed web page. Keep that in mind.
Tips & Tricks
We have already found out that user scripts usually change the design of web pages. Therefore, the main tasks that confront developers are related to DOM programming, namely, the manipulation of the DOM model of web pages. The problem here is that sometimes it is very difficult to achieve adequate script operation on anti-semantic sites. And I would like to give a few suggestions for GM developers.
Opera, Safari and Firefox have built-in support for XPath, via the document.evaluate () function. A good
description of this feature is in
MDC . For those who do not know, XPath (XML Path Language) is a language for accessing parts of an XML document. In the case of the web, this definition is true for HTML. Excellent tutorial is on
ZVON.org . The essence of the method is that you create and send a “request” to the DOM model, and in return you get an iterator with all the nodes that satisfy this request.
It is important to know that you cannot directly modify these nodes in the iterator, since any change rebuilds the DOM, thus making the iterator invalid. Therefore, first create an array and copy references to these nodes there, and then work with them. In the example in the MDC, all this is considered.
In IE, there is also a partial support for evaluate, which is implemented through a
hack , created by Dimitri Glazkov and Mehdi Hassan.
We added it to our
JS-Extender , correcting some bugs in it. However, we did not manage to perform complex XPath queries, so we do not use this function in IE.
Another important point worth noting is that when using the element.childNodes property, FF considers text line breaks between tags to be text nodes. For example, a div with id = container will have not three, but five child nodes:
<div id = "container">
<div> content1 </ div>
<div> content2 </ div>
</ div>
Be carefull!
And last but most important. In JS, there is a window object, which, as it were, is a global namespace for all global JS entities. if we write
var myVar = 1;
it will be available in
window.myVar or window ['myVar'].
So, GM also has a window, but it is a wrapper around the window itself of the web page. This is done to ensure that your code does not overlap with the original page code and does not interfere with it. But there are situations when you need to directly access the window itself, for example, to get the value of a site variable. The global property unsafeWindow, which provides access to it, comes to the rescue.
If you are writing a cross-browser user script, keep in mind that unsafeWindow is only in GM, it is not in Opera. Therefore, it is better to start the global variable right away and put the window you need into it, for example:
var aWindow = (typeof unsafeWindow! = 'undefined')? unsafeWindow: window;
A spoon of tar
Despite the great opportunities, GM has a significant drawback, which is the lack of a centralized mechanism for updating user scripts.
There are several attempts to solve this problem:
yoast.com/greasemonkey-auto-update-notificationsplintor.wordpress.com/2007/05/01/greasemonkey-wish-auto-update-user-scriptsuserscripts.org/scripts/show/2296At the moment I am not satisfied with any of them. We took this question to the development of the poem, and certainly come up with an elegant solution to the problem. What I will tell you separately.
In general, we can say that GreaseMonkey is a special case of the mechanism for managing user scripts. In Opera, they are supported without any extensions, according to information received from
pepelsbey there is a plugin for Safari, which allows you to run these scripts -
GreaseKit , according to information received from
jursovet ,
script support is already implemented for Chrome
On this I consider my report complete. Thank you for reading.