Controlling userscripts in sub windows

From GreaseSpot

Jump to: navigation, search

Sometimes a (top-level) userscript will open various URLs in sub-windows. As windows, the same or a different userscript may apply to them. This section describes ways in which a top-level userscript can control whether or how userscripts are to be run on the sub-windows.

There are four ways to open sub-windows.

Opening a separate window:

window.open(url name, features, replaces);  

Opening a new tab:

GM_openInTab(url);

Setting the .src of a <frame> or <iframe> in the document. In a simple case this may consist of adding a .src bound <iframe> to the document.

var ifr1 = document.createElement('iframe');
ifr1.src = "http://example.com/";
document.body.appendChild(ifr1);

[edit] Passing parameters in the URL hash (#) field.

URLs (really URIs) may contain a terminal text field that is marked with a hash character (#). The # and following characters can often be accessed via the property .hash. E.g.

document.location.hash
a.href.hash

The default browser behavior for opening a URL that contains a .hash field is to use it to determine initial scrolling into the page – to some DOM node with an .id or .name equal to the .hash. For example the URL

http://wiki.greasespot.net/Main_Page#Getting_Started

should cause the retrieved page to be displayed starting with the 'Getting_Started' header.

However no browsers complain if .hash cannot be found as a .id or .name. This means that .hash can be used to pass parameters to control userscripts on sub-windows. Communication at the level of URL text strings has no security constraints (such as common domain) on its usage.

In the simplest case, a userscript can pass a .hash to interact with the @include or @exclude metadaters headers of a co-developed userscript that might apply to a sub-window. For example, to prevent a sub-userscript from running its header could contain

 // @exclude *#noGrease

which would exclude it from applying to any sub-window that was opened via a URL appended with ‘#noGrease’.

In the more general case, the .hash can encode information to tell sub-userscripts specific things to do. Often the userscripts processing a domain for some particular task are consolidated – i.e. there is just one userscript that applies to both the top-level window and any opened sub-windows. Such a script can decide what to do by examining

document.location.hash

For example a consolidated userscript might contain code like:

function Main(){
 var hash = document.location.hash;
 if (!hash) return doTopLevel();
 var fun = {'#noGrease': function(){}, '#case1': doCase1, '#case2': doCase2}[hash];
 if (fun) return fun(); 
} 
Main();

When passing arbitrary parameters (including such as URLs), they may need to be encoded so the URL is valid. For example a consolidated userscript named 'script8' might contain code like:

 // top window passing parameters to a sub-window
 var hash = '#script8' + encodeURIComponent(params);

and

// sub-window accessing parameters
var m = document.location.hash.match(/^\#script8(.*)/);
if (m) params = decodeURIComponent(m[1]); 

NOTE: The .search field (?) of a URL can often be used in ways similar to the .hash field. In general this is a bad idea because the .search field is sent to the remote server and it may barf when given what it considers to be an invalid search request.

Personal tools