<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://commons.oreilly.com/wiki/skins/common/feed.css?97"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://commons.oreilly.com/wiki/index.php?title=Greasemonkey_Hacks/Linkmania!&amp;action=history&amp;feed=atom</id>
		<title>Greasemonkey Hacks/Linkmania! - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://commons.oreilly.com/wiki/index.php?title=Greasemonkey_Hacks/Linkmania!&amp;action=history&amp;feed=atom"/>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=Greasemonkey_Hacks/Linkmania%21&amp;action=history"/>
		<updated>2013-05-18T14:53:02Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.11.0</generator>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=Greasemonkey_Hacks/Linkmania%21&amp;diff=9631&amp;oldid=prev</id>
		<title>Docbook2Wiki: Initial conversion from Docbook</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=Greasemonkey_Hacks/Linkmania%21&amp;diff=9631&amp;oldid=prev"/>
				<updated>2008-03-11T23:10:08Z</updated>
		
		<summary type="html">&lt;p&gt;Initial conversion from Docbook&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 23:10, 11 March 2008&lt;/td&gt;
			&lt;/tr&gt;
		&lt;/table&gt;</summary>
		<author><name>Docbook2Wiki</name></author>	</entry>

	<entry>
		<id>http://commons.oreilly.com/wiki/index.php?title=Greasemonkey_Hacks/Linkmania%21&amp;diff=7954&amp;oldid=prev</id>
		<title>Docbook2Wiki: Initial conversion from Docbook</title>
		<link rel="alternate" type="text/html" href="http://commons.oreilly.com/wiki/index.php?title=Greasemonkey_Hacks/Linkmania%21&amp;diff=7954&amp;oldid=prev"/>
				<updated>2008-03-11T20:29:52Z</updated>
		
		<summary type="html">&lt;p&gt;Initial conversion from Docbook&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Greasemonkey Hacks/TOC}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hacks 13–20: Introduction ==&lt;br /&gt;
&lt;br /&gt;
The Web revolves around links. Links take you to a site, let you navigate within it, and finally take you somewhere else. But not all links are created equal. Some links launch a new window without your permission. Some launch external applications. Some execute a piece of JavaScript code, which means they could do almost anything. And some links aren't even clickable.&lt;br /&gt;
&lt;br /&gt;
The first step to reclaiming your browser is taking control of links.&lt;br /&gt;
&lt;br /&gt;
== Turn Naked URLs into Hyperlinks ==&lt;br /&gt;
&lt;br /&gt;
'''Make every URL clickable'''.&lt;br /&gt;
&lt;br /&gt;
Have you ever visited a page that displayed a ''naked'' URL that you couldn't click? That is, the URL is displayed as plain text on the page, and you need to manually copy the text and paste it into a new browser window to follow the link. I run into this problem all the time while reading weblogs, because many weblog publishing systems allow readers to submit comments (including URLs) but just display the comment verbatim without checking whether the comment includes a naked URL. This hack turns all such URLs into clickable links.&lt;br /&gt;
&lt;br /&gt;
=== The Code ===&lt;br /&gt;
&lt;br /&gt;
This user script runs on all pages. To ensure that it does not affect URLs that are already linked, it uses an XPath query that includes &amp;lt;tt&amp;gt;not(ancestor::a)&amp;lt;/tt&amp;gt;. To ensure that it does affect URLs in uppercase, the XPath query also includes &amp;quot;&amp;lt;tt&amp;gt;contains(translate(., 'HTTP', 'http'), 'http')]&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Once we find a text node that definitely contains an unlinked URL, there could be more than one URL within it, so we need to convert ''all'' the URLs while keeping the surrounding text intact. We replace the text with an empty &amp;lt;tt&amp;gt;&amp;amp;lt;span&amp;gt;&amp;lt;/tt&amp;gt; element as a placeholder and then incrementally reinsert each non-URL text snippet and each constructed URL link.&lt;br /&gt;
&lt;br /&gt;
Save the following user script as ''linkify.user.js'':&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	// ==UserScript==&lt;br /&gt;
	// @name		  Linkify&lt;br /&gt;
	// @namespace	  http://youngpup.net/userscripts&lt;br /&gt;
	// @description   Turn plain-&amp;lt;/nowiki&amp;gt;linkstext URLstext URLs into linkshyperlinks&lt;br /&gt;
 	// @include *&lt;br /&gt;
 	// ==/UserScript==&lt;br /&gt;
 &lt;br /&gt;
 	// based on code by Aaron Boodman&lt;br /&gt;
 	// and included here with his gracious permission&lt;br /&gt;
 &lt;br /&gt;
 	var urlRegex = /\b(https?:\/\/[^\s+\&amp;quot;\&amp;lt;\&amp;gt;]+)/ig;&lt;br /&gt;
 	var snapTextElements = document.evaluate(&amp;quot;//text()[not(ancestor::a) &amp;quot; + &lt;br /&gt;
 		&amp;quot;and not(ancestor::script) and not(ancestor::style) and &amp;quot; + &lt;br /&gt;
 		&amp;quot;contains(translate(., 'HTTP', 'http'), 'http')]&amp;quot;, &lt;br /&gt;
 		document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);&lt;br /&gt;
 	for (var i = snapTextElements.snapshotLength - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
 		var elmText = snapTextElements.snapshotItem(i);&lt;br /&gt;
 		if (urlRegex.test(elmText.nodeValue)) {&lt;br /&gt;
 			var elmSpan = document.createElement(&amp;quot;span&amp;quot;);&lt;br /&gt;
 			var sURLText = elmText.nodeValue;&lt;br /&gt;
 			elmText.parentNode.replaceChild(elmSpan, elmText);&lt;br /&gt;
 			urlRegex.lastIndex = 0;&lt;br /&gt;
 			for (var match = null, lastLastIndex = 0;&lt;br /&gt;
 				 (match = urlRegex.exec(sURLText)); ) { &lt;br /&gt;
 				elmSpan.appendChild(document.createTextNode(&lt;br /&gt;
 				sURLText.substring(lastLastIndex, match.index))); &lt;br /&gt;
 				var elmLink = document.createElement(&amp;quot;a&amp;quot;); &lt;br /&gt;
 				elmLink.setAttribute(&amp;quot;href&amp;quot;, match[0]); &lt;br /&gt;
 				elmLink.appendChild(document.createTextNode(match[0])); &lt;br /&gt;
 				elmSpan.appendChild(elmLink); &lt;br /&gt;
 				lastLastIndex = urlRegex.lastIndex;&lt;br /&gt;
 			}&lt;br /&gt;
 			elmSpan.appendChild(document.createTextNode(&lt;br /&gt;
 				sURLText.substring(lastLastIndex)));&lt;br /&gt;
 			elmSpan.normalize();&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
&lt;br /&gt;
=== Running the Hack ===&lt;br /&gt;
&lt;br /&gt;
Before installing the user script, go to ''http://www.mnot.net/blog/2005/05/18/WADL'', an article published by Mark Nottingham on his weblog. I followed Mark's weblog for many years, and the only thing I disliked was that the links I posted in the comments section would be displayed as plain text (i.e., not as hyperlinks). The comments section at the end of this article has several contributed URLs that display as plain text, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-1|Figure 2-1]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-1&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-1. Comments with plain-text URLs'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt90.png|Comments with plain-text URLs]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, install the user script (Tools → Install This User Script), and refresh ''http://www.mnot.net/blog/2005/05/18/WADL''. All the URLs in the comments section are now real hyperlinks, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-2|Figure 2-2]].&lt;br /&gt;
&lt;br /&gt;
=== Hacking the Hack ===&lt;br /&gt;
&lt;br /&gt;
You might want to distinguish between links that were part of the original page and links that were created by this script. You can do this by adding a custom style to the &amp;lt;tt&amp;gt;elmLink&amp;lt;/tt&amp;gt; element.&lt;br /&gt;
&lt;br /&gt;
Change this line:&lt;br /&gt;
&lt;br /&gt;
 	var elmLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
to this:&lt;br /&gt;
&lt;br /&gt;
 	var elmLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
 	elmLink.title = 'linkified by Greasemonkey!';&lt;br /&gt;
 	elmLink.style.textDecoration = 'none';&lt;br /&gt;
 	elmLink.style.borderBottom = '1px dotted red';&lt;br /&gt;
&lt;br /&gt;
The ''linkified'' URLs will now be underlined with a dotted red line, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-3|Figure 2-3]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-2&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-2. Comments with clickable URLs'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt93.png|Comments with clickable URLs]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-3&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-3. Custom styles on linkified URLs'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt94.png|Custom styles on linkified URLs]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Force Offsite Links to Open in a New Window ==&lt;br /&gt;
&lt;br /&gt;
'''Keep your browser organized by automatically opening each site in its own window'''.&lt;br /&gt;
&lt;br /&gt;
I originally wrote this user script after someone posted a request to the Greasemonkey script repository. I personally like to open links in a new tab in the current window, but some people prefer to open a separate window for each site. Offsite Blank lets you do this automatically, by forcing offsite links to open in a new window.&lt;br /&gt;
&lt;br /&gt;
=== The Code ===&lt;br /&gt;
&lt;br /&gt;
This user script runs on remote web sites (but not, for example, on HTML documents stored on your local machine that you open from the File → Open menu). Since search engines exist to provide links to other pages, and I find it annoying for search result links to open new links, I've excluded Google and Yahoo! by default.&lt;br /&gt;
&lt;br /&gt;
The code itself breaks down into four steps:&lt;br /&gt;
&lt;br /&gt;
# Get the domain of the current page.&lt;br /&gt;
# Get a list of all the links on the page.&lt;br /&gt;
# Compare the domain of each link to the domain of the page.&lt;br /&gt;
# If the domains don't match, set the &amp;lt;tt&amp;gt;target&amp;lt;/tt&amp;gt; attribute of the link so that it opens in a new window.&lt;br /&gt;
&lt;br /&gt;
Save the following user script as ''offsiteblank.user.js'':&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	// ==UserScript==&lt;br /&gt;
	// @name		  Offsite Blank&lt;br /&gt;
	// @namespace	  http://diveintomark.org/projects/greasemonkey/&lt;br /&gt;
	// @description	  force &amp;lt;/nowiki&amp;gt;linksoffsite linksoffsite links to open in a new window&lt;br /&gt;
 	// @include		  http*://*&lt;br /&gt;
 	// @exclude       ''&amp;lt;nowiki&amp;gt;http://*.google.tld/*&amp;lt;/nowiki&amp;gt;''&amp;lt;nowiki&amp;gt;&lt;br /&gt;
	// @exclude       http://*.yahoo.tld/*&lt;br /&gt;
	// ==/UserScript==&lt;br /&gt;
&lt;br /&gt;
	var sCurrentHost = location.host;&lt;br /&gt;
	var arLinks = document.links;&lt;br /&gt;
	for (var i = arLinks.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
		var elmLink = arLinks[i];&lt;br /&gt;
		if (elmLink.host &amp;amp;&amp;amp; elmLink.host != sCurrentHost) {&lt;br /&gt;
				elmLink.target = &amp;quot;_blank&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Running the Hack ===&lt;br /&gt;
&lt;br /&gt;
After installing the user script (Tools → Install This User Script), go to ''http://www.fsf.org''. Click on one of the links in the navigation bar, such as &amp;quot;About us.&amp;quot; The link will open in the same window, as normal.&lt;br /&gt;
&lt;br /&gt;
Go back to ''http://www.fsf.org'', scroll to the bottom of the page, and click the Plone Powered link to visit ''http://plone.org''. Since the link points to a page on another site, Firefox will automatically open the link in a new window, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-4|Figure 2-4]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-4&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-4. Offsite link opened in a new window'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt96.png|Offsite link opened in a new window]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hacking the Hack ===&lt;br /&gt;
&lt;br /&gt;
This hack is somewhat naive about what constitutes an ''offsite'' link. For example, if you visit ''http://www.slashdot.org'' and click a link on ''http://developers.slashdot.org'', the script will force the link to open in a new window, because it considers ''developers.slashdot.org'' to be a different site than ''www.slashdot.org''. We can fix this by modifying the user script to compare only the last part of the domain name.&lt;br /&gt;
&lt;br /&gt;
Save the following user script as ''offsiteblank2.user.js'':&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	// ==UserScript==&lt;br /&gt;
	// @name          Offsite Blank 2&lt;br /&gt;
	// @namespace	  http://diveintomark.org/projects/greasemonkey/&lt;br /&gt;
	// @description   force &amp;lt;/nowiki&amp;gt;offsite linksoffsite links to open in a new window	&lt;br /&gt;
 	// @include		  http*://*&lt;br /&gt;
 	// @exclude		  http*://*.google.tld/*&lt;br /&gt;
 	// @exclude		  http*://*.yahoo.tld/*&lt;br /&gt;
 	// ==/UserScript== &lt;br /&gt;
 &lt;br /&gt;
 	var NUMBER_OF_PARTS = 2; &lt;br /&gt;
 &lt;br /&gt;
 	var sCurrentHost = window.location.host;&lt;br /&gt;
 	'''var arParts = sCurrentHost.split('.');'''&lt;br /&gt;
 '''	if (arParts.length &amp;gt; NUMBER_OF_PARTS) {'''&lt;br /&gt;
 '''		sCurrentHost = [arParts[arParts.length - NUMBER_OF_PARTS],'''&lt;br /&gt;
 '''&amp;lt;nowiki&amp;gt;				arParts[arParts.length - 1]].join('.');&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
 '''	}'''&lt;br /&gt;
 	var linksarLinks = document.getElementsByTagName('a');&lt;br /&gt;
 	for (var i = arLinks.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
 		var elmLink = arLinks[i];&lt;br /&gt;
 		var sHost = elmLink.host;&lt;br /&gt;
 		if (!sHost) { continue; }&lt;br /&gt;
 	'''var arLinkParts = sHost.split('.');'''&lt;br /&gt;
 '''		if (arLinkParts.length &amp;gt; NUMBER_OF_PARTS) {'''&lt;br /&gt;
 '''			sHost = [arLinkParts[arLinkParts.length - NUMBER_OF_PARTS],'''&lt;br /&gt;
 '''&amp;lt;nowiki&amp;gt;				 arLinkParts[arLinkParts.length - 1]].join('.');&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
 '''		}'''&lt;br /&gt;
 	if (sHost != sCurrentHost) {&lt;br /&gt;
 			elmLink.target = &amp;quot;_blank&amp;quot;;&lt;br /&gt;
         }&lt;br /&gt;
 	}&lt;br /&gt;
&lt;br /&gt;
This script is still naive about what constitutes an ''offsite'' link; it's just naive in a different way than the first script. On sites such as ''http://www.amazon.co.uk'', this script thinks the ''current'' domain is ''co.uk'', instead of ''amazon.co.uk''. You can further refine this behavior by changing the &amp;lt;tt&amp;gt;NUMBER_OF_PARTS&amp;lt;/tt&amp;gt; constant at the top of the script from 2 to 3.&lt;br /&gt;
&lt;br /&gt;
== Fix Broken Pop-up Links ==&lt;br /&gt;
&lt;br /&gt;
'''Change javascript: pseudo-protocol pop-up windows into normal hyperlinks'''.&lt;br /&gt;
&lt;br /&gt;
Advanced browser users do more than just click hyperlinks. They also right-click them, print them, and save them to disk. All these additional behaviors are broken when web developers incorrectly use the &amp;lt;tt&amp;gt;javascript&amp;lt;/tt&amp;gt;: pseudo-protocol to create pop-up windows.&lt;br /&gt;
&lt;br /&gt;
A broken pop up looks like this:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	&amp;lt;a href=&amp;quot;javascript:popup('http://youngpup.net/')&amp;quot;&amp;gt;go to youngpup.net&amp;lt;/a&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, the web developer is attempting to create a link that opens in a new pop-up window. Unfortunately, the value of the &amp;lt;tt&amp;gt;href&amp;lt;/tt&amp;gt; attribute is not a valid URL. It's just JavaScript, which works only in the context of the current page. This means that if a user right-clicks the link and tries to open it in a new window, the &amp;lt;tt&amp;gt;popup&amp;lt;/tt&amp;gt; function is undefined and the user gets an error message. Likewise, if the user attempts to save or print the contents of the hyperlink, the browser first has to download it, which it cannot do because the &amp;lt;tt&amp;gt;href&amp;lt;/tt&amp;gt; doesn't contain a URL; it contains a random JavaScript statement.&lt;br /&gt;
&lt;br /&gt;
There is no reason for web developers ever to do this. You can easily write annoying pop-up windows ''and'' retain the benefits of regular hyperlinks, by adding an &amp;lt;tt&amp;gt;onclick&amp;lt;/tt&amp;gt; handler to a regular hyperlink:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	&amp;lt;a href=&amp;quot;http://youngpup.net/&amp;quot; &lt;br /&gt;
           &amp;lt;/nowiki&amp;gt;'''onclick=&amp;quot;window.open(this.href); return false;&amp;quot;'''&amp;gt; &lt;br /&gt;
 		 go to youngpup.net &lt;br /&gt;
 	&amp;lt;/a&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Using Greasemonkey, we can scan for &amp;lt;tt&amp;gt;javascript&amp;lt;/tt&amp;gt;: links that appear to open pop-up windows and then change them to use an &amp;lt;tt&amp;gt;onclick&amp;lt;/tt&amp;gt; handler instead.&lt;br /&gt;
&lt;br /&gt;
=== The Code ===&lt;br /&gt;
&lt;br /&gt;
This user script runs on every page. It loops through every link on the page, looking for &amp;lt;tt&amp;gt;javascript&amp;lt;/tt&amp;gt;: URLs. If the link's &amp;lt;tt&amp;gt;href&amp;lt;/tt&amp;gt; attribute begins with &amp;lt;tt&amp;gt;javascript&amp;lt;/tt&amp;gt;:, the script checks whether it appears to open a pop-up window by looking for something that looks like a URL after the &amp;lt;tt&amp;gt;javascript&amp;lt;/tt&amp;gt;: keyword. Since the overwhelming majority of web authors that use &amp;quot;&amp;lt;tt&amp;gt;javascript&amp;lt;/tt&amp;gt;:&amp;quot; links use them to open pop-up windows, this should not have too many false positives.&lt;br /&gt;
&lt;br /&gt;
If the script determines that the link is trying to open a pop-up window, it attempts to reconstruct the target URL. It changes the surrounding &amp;lt;tt&amp;gt;&amp;lt;a&amp;gt;&amp;lt;/tt&amp;gt; element to use a normal &amp;lt;tt&amp;gt;href&amp;lt;/tt&amp;gt; attribute and move the JavaScript code to the &amp;lt;tt&amp;gt;onclick&amp;lt;/tt&amp;gt; event handler.&lt;br /&gt;
&lt;br /&gt;
Save the following user script as ''popupfixer.user.js'':&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	// ==UserScript==&lt;br /&gt;
	// @name           Popup Window Fixer&lt;br /&gt;
	// @namespace	   http://youngpup.net/userscripts&lt;br /&gt;
	// @description	   Fixes javascript: pseudo-links that popup windows&lt;br /&gt;
	// @include        *&lt;br /&gt;
	// ==/UserScript==&lt;br /&gt;
&lt;br /&gt;
	const urlRegex = /\b(https?:\/\/[^\s+\&amp;quot;\&amp;lt;\&amp;gt;\'\(\)]+)/ig; &lt;br /&gt;
	var candidates = document.getElementsByTagName(&amp;quot;a&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	for (var cand = null, i = 0; (cand = candidates[i]); i++) {&lt;br /&gt;
		if (cand.getAttribute(&amp;quot;onclick&amp;quot;) == null &amp;amp;&amp;amp;        &lt;br /&gt;
			cand.href.toLowerCase().indexOf(&amp;quot;javascript:&amp;quot;) == 0) { &lt;br /&gt;
			var match = cand.href.match(urlRegex); &lt;br /&gt;
			if (!match) { continue; } &lt;br /&gt;
			cand.href = match[0];&lt;br /&gt;
		} &lt;br /&gt;
	}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Running the Hack ===&lt;br /&gt;
&lt;br /&gt;
Before installing the script, create a file called ''testpopup.html'' with the following contents:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	&amp;lt;html&amp;gt;&lt;br /&gt;
	&amp;lt;head&amp;gt;&lt;br /&gt;
	&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
	function popup(url) { window.open(url); }&lt;br /&gt;
	&amp;lt;/script&amp;gt;&lt;br /&gt;
	&amp;lt;/head&amp;gt;&lt;br /&gt;
	&amp;lt;body&amp;gt;&lt;br /&gt;
	&amp;lt;a href=&amp;quot;javascript:popup('http://youngpup.net/')&amp;quot;&amp;gt;Aaron's home page&amp;lt;/a&amp;gt;&lt;br /&gt;
	&amp;lt;/body&amp;gt;&lt;br /&gt;
	&amp;lt;/html&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save the file and open it in Firefox (File → Open…). When you hover over the link, the status bar displays the JavaScript. When you click the link, it does indeed open ''http://youngpup.net''. However, if you right-click the link and select &amp;quot;Open in new tab,&amp;quot; the link fails, because the pop-up function is defined only on the current page, not in the new tab.&lt;br /&gt;
&lt;br /&gt;
Now, install the user script (Tools → Install This User Script) and refresh the test page. Hover over the link again, and you will see in the status bar that the link now points directly to the URL, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-5|Figure 2-5]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-5&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-5. Fixed pop-up link'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt102.png|Fixed pop-up link]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means you can right-click the link and open it in a new tab, save the target page to your local computer, or print it. When you click the link directly, it still opens an annoying pop-up window, as the developer intended.&lt;br /&gt;
&lt;br /&gt;
=== Hacking the Hack ===&lt;br /&gt;
&lt;br /&gt;
There are various problems with this code, all stemming from the fact that it is hard to know for sure that a &amp;quot;&amp;lt;tt&amp;gt;javascript&amp;lt;/tt&amp;gt;:&amp;quot; link is supposed to open a pop up. For example, this script cannot detect any of these pop-up links:&lt;br /&gt;
&lt;br /&gt;
 	&amp;lt;a href=&amp;quot;javascript:popup('foo.html')&amp;quot;&amp;gt;&lt;br /&gt;
 	&amp;lt;a href=&amp;quot;javascript:popup('foo/bar/')&amp;quot;&amp;gt;&lt;br /&gt;
 	&amp;lt;a href=&amp;quot;javascript:popupHomePage()&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All we can say for sure is that hyperlinks that use the &amp;quot;&amp;lt;tt&amp;gt;javascript&amp;lt;/tt&amp;gt;:&amp;quot; pseudo-protocol are not really hyperlinks. So, maybe they shouldn't look like hyperlinks. If they didn't, you'd be less confused when they didn't act like hyperlinks.&lt;br /&gt;
&lt;br /&gt;
Save the following user script as ''popupstyler.user.js'':&lt;br /&gt;
&lt;br /&gt;
 	var candidates = document.links;&lt;br /&gt;
 	for (var cand = null, i = 0; (cand = candidates[i]); i++) {&lt;br /&gt;
 		if (cand.href.toLowerCase().indexOf(&amp;quot;javascript:&amp;quot;) == 0) {&lt;br /&gt;
 			with (cand.style) {&lt;br /&gt;
 				background = &amp;quot;#ddd&amp;quot;;&lt;br /&gt;
 				borderTop = &amp;quot;2px solid white&amp;quot;;&lt;br /&gt;
 				borderLeft = &amp;quot;2px solid white&amp;quot;;&lt;br /&gt;
 				borderRight = &amp;quot;2px solid #999&amp;quot;;&lt;br /&gt;
 				borderBottom = &amp;quot;2px solid #999&amp;quot;;&lt;br /&gt;
 				padding = &amp;quot;.5ex 1ex&amp;quot;;&lt;br /&gt;
 				color = &amp;quot;black&amp;quot;;&lt;br /&gt;
 				textDecoration = &amp;quot;none&amp;quot;;&lt;br /&gt;
 			}&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
&lt;br /&gt;
Uninstall ''popupfixer.user.js'', install ''popupstyler.user.js'', and refresh the test page. (In general, you can run the two scripts simultaneously, just not in this demonstration.) The &amp;quot;&amp;lt;tt&amp;gt;javascript&amp;lt;/tt&amp;gt;:&amp;quot; link now appears to be a button, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-6|Figure 2-6]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-6&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-6. Styled pop-up link'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt105.png|Styled pop-up link]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is no complete solution that will work with every possible &amp;quot;&amp;lt;tt&amp;gt;javascript&amp;lt;/tt&amp;gt;:&amp;quot; pop-up link, since there are so many variations of JavaScript code to open a new window. In theory, you could redefine the &amp;lt;tt&amp;gt;window.open&amp;lt;/tt&amp;gt; function and manually call the JavaScript code in each link, but this could have serious unintended side effects if the link did something other than open a window. Your best bet is a combination of fixing the links you can fix and styling the rest.&lt;br /&gt;
&lt;br /&gt;
—''Aaron Boodman''&lt;br /&gt;
&lt;br /&gt;
== Remove URL Redirections ==&lt;br /&gt;
&lt;br /&gt;
'''Cut out the middleman and make links point directly to where you want to go'''.&lt;br /&gt;
&lt;br /&gt;
Many portal sites use redirection links for links that point to other sites. The link first goes to a tracking page on the portal, which logs your click and sends you on your way to the external site. Not only is this an invasion of privacy, but it's also slower, since you need to load the tracking page before you are redirected to the page you actually want to read. This hack detects such redirection links and converts them to direct links that take you straight to the final destination.&lt;br /&gt;
&lt;br /&gt;
=== The Code ===&lt;br /&gt;
&lt;br /&gt;
This user script runs on all pages, except for a small list of pages where it is known to cause problems with false positives. It uses the &amp;lt;tt&amp;gt;document.links&amp;lt;/tt&amp;gt; collection to find all the links on the page and checks whether the URL of the link includes another URL within it. If it finds one, it extracts it and unescapes it, and replaces the original URL.&lt;br /&gt;
&lt;br /&gt;
Save the following user script as ''nomiddleman.user.js'':&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	// ==UserScript==&lt;br /&gt;
	// @name        NoMiddleMan&lt;br /&gt;
	// @namespace   http://0x539.blogspot.com/&lt;br /&gt;
	// @description Rewrites URLs to remove redirection scripts&lt;br /&gt;
	// @include     *&lt;br /&gt;
	// @exclude		http://del.icio.us/*&lt;br /&gt;
	// @exclude     http://*bloglines.com/*&lt;br /&gt;
	// @exclude		http://web.archive.org/*&lt;br /&gt;
	// @exclude		http://*wists.com/*&lt;br /&gt;
	// ==/UserScript==&lt;br /&gt;
&lt;br /&gt;
	// based on code by Albert Bachand&lt;br /&gt;
	// and included here with his gracious permission&lt;br /&gt;
	// http://kungfoo.webhop.org/&amp;lt;/nowiki&amp;gt;code samplesnomiddleman.user.jsnomiddleman.user.js&lt;br /&gt;
 &lt;br /&gt;
 	for (var i=0; i&amp;lt;document.linkslinks.length; i++) { &lt;br /&gt;
 		 var link, temp, start, linksURL redirection&amp;lt;nowiki&amp;gt;url, qindex, end; &lt;br /&gt;
		 link = document.links[i];&lt;br /&gt;
&lt;br /&gt;
		 // Special case for Google results (assumes English language)&lt;br /&gt;
		 if (link.text == 'Cached' ||&lt;br /&gt;
			 /Similar.*?pages/.exec(link.text)) {&lt;br /&gt;
			 continue;&lt;br /&gt;
		 }&lt;br /&gt;
&lt;br /&gt;
		 temp = link.href.toLowerCase();&lt;br /&gt;
&lt;br /&gt;
		 // ignore javascript links and GeoURL&lt;br /&gt;
		 if (temp.indexOf('javascript:') == 0 ||&lt;br /&gt;
		 temp.indexOf('geourl.org') != -1) {&lt;br /&gt;
			 continue;&lt;br /&gt;
		 }&lt;br /&gt;
&lt;br /&gt;
		 // find the start of the (last) real url&lt;br /&gt;
		 start = Math.max(temp.lastIndexOf('http%3a'),&lt;br /&gt;
				  temp.lastIndexOf('http%253a'),&lt;br /&gt;
				  temp.lastIndexOf('http:'));&lt;br /&gt;
&lt;br /&gt;
		 if (start &amp;lt;= 0) { &lt;br /&gt;
			 // special case: handle redirect url without a 'http:' part &lt;br /&gt;
			 start = link.href.lastIndexOf('www.'); &lt;br /&gt;
			 if (start &amp;lt; 10) {&lt;br /&gt;
				 start = 0;&lt;br /&gt;
			 } else { &lt;br /&gt;
				 link.href = link.href.substring(0, start) + &lt;br /&gt;
				 'http://' + link.href.substring(start);&lt;br /&gt;
			 }&lt;br /&gt;
		 }&lt;br /&gt;
&lt;br /&gt;
		 // we are most likely looking at a &amp;lt;/nowiki&amp;gt;URLsredirectionredirection link&lt;br /&gt;
 		 if (start &amp;gt; 0) {&lt;br /&gt;
 			 url = link.href.substring(start);&lt;br /&gt;
 &lt;br /&gt;
 			 // check whether the real url is a parameter &lt;br /&gt;
 			 qindex = link.href.indexOf('?'); &lt;br /&gt;
 			 if (qindex &amp;gt; -1 &amp;amp;&amp;amp; qindex &amp;lt; start) {&lt;br /&gt;
 			     // it's a parameter, extract only the url&lt;br /&gt;
 				 end = url.indexOf('&amp;amp;');&lt;br /&gt;
 				 if (end &amp;gt; -1) {&lt;br /&gt;
 				 url = url.substring(0, end);&lt;br /&gt;
 				 }&lt;br /&gt;
 			 }&lt;br /&gt;
 			 // handle Yahoo's chained redirections&lt;br /&gt;
 			 var temp = url;&lt;br /&gt;
 			 url = unescape(url);&lt;br /&gt;
 &lt;br /&gt;
 			 while (temp != linksURL redirectionurl) {&lt;br /&gt;
 				 temp = url;&lt;br /&gt;
 				 url = unescape(url);&lt;br /&gt;
 			 }&lt;br /&gt;
 			 // and we're done&lt;br /&gt;
 			 link.href = url.replace(/&amp;amp;amp;amp;/g, '&amp;amp;');&lt;br /&gt;
 		 }&lt;br /&gt;
 	}&lt;br /&gt;
&lt;br /&gt;
=== Running the Hack ===&lt;br /&gt;
&lt;br /&gt;
Before installing the user script, go to ''http://www.yahoo.com'' and search for &amp;lt;tt&amp;gt;greasemonkey&amp;lt;/tt&amp;gt;. In the list of search results, each linked page is really a redirect through Yahoo!'s servers, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-7|Figure 2-7]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-7&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-7. Yahoo! Redirection URL'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt107.png|Yahoo! Redirection URL]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, install the user script (Tools → Install This User Script), go back to ''http://www.yahoo.com'', and execute the same search. The link to the search result page now points directly to ''http://dream.sims.berkeley.edu/~ryanshaw/wordpress/2005/02/18/greasemonkey-stole-your-job-and-your-business-model/'', as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-8|Figure 2-8]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-8&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-8. Yahoo! Direct URL'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt108.png|Yahoo! Direct URL]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are a variety of ways that sites can redirect links through a tracking page. This script doesn't handle all of them, but it handles the most common cases and a few special cases used by popular sites (such as Yahoo!). The author maintains a weblog at ''http://0x539.blogspot.com/'' where you can check for updates to this script.&lt;br /&gt;
&lt;br /&gt;
== Warn Before Opening PDF Links ==&lt;br /&gt;
&lt;br /&gt;
'''Make your browser double-check that you really want to open that monstrous PDF'''.&lt;br /&gt;
&lt;br /&gt;
How many times has this happened to you? You're searching for something, or just browsing, and click on a promising-looking link. Suddenly, your browser slows to a crawl, and you see the dreaded &amp;quot;Adobe Acrobat Reader&amp;quot; splash screen. Oh no, you've just opened a PDF link, and your browser is launching the helper application from hell.&lt;br /&gt;
&lt;br /&gt;
This hack saves you the trouble, by popping up a dialog box when you click on a PDF file to ask you if you're sure you want to continue. If you cancel, you're left on the original page and can continue browsing in peace.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tip&amp;quot;&amp;gt;&lt;br /&gt;
'''Tip'''&lt;br /&gt;
&lt;br /&gt;
This hack is derived from a Firefox extension called TargetAlert, which offers more features and customization options. Download it at ''http://bolinfest.com/targetalert/''.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Code ===&lt;br /&gt;
&lt;br /&gt;
This user script runs on all pages. It iterates through the &amp;lt;tt&amp;gt;document.links&amp;lt;/tt&amp;gt; collection, looking for links pointing to URLs ending in ''.pdf''. For each link, it attaches an &amp;lt;tt&amp;gt;onclick&amp;lt;/tt&amp;gt; handler that calls the &amp;lt;tt&amp;gt;window.confirm&amp;lt;/tt&amp;gt; function to ask you if you really want to open the PDF document.&lt;br /&gt;
&lt;br /&gt;
Save the following user script as ''pdfwarn.user.js'':&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	// ==UserScript==&lt;br /&gt;
	// @name          PDF Warn&lt;br /&gt;
	// @namespace     http://www.sencer.de/&lt;br /&gt;
	// @description   Ask before opening PDF links&lt;br /&gt;
	// @include       *&lt;br /&gt;
	// ==/UserScript==&lt;br /&gt;
&lt;br /&gt;
	// based on code by Sencer Yurdagül and Michael Bolin&lt;br /&gt;
	// and included here with their gracious permission&lt;br /&gt;
	// http://www.sencer.de/code/greasemonkey/&amp;lt;/nowiki&amp;gt;code samplespdfwarn.user.jspdfwarn.user.js&lt;br /&gt;
 &lt;br /&gt;
 	for (var i = document.links.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
 		var elmLink = document.links[i];&lt;br /&gt;
 		if (elmLink.href &amp;amp;&amp;amp; elmLink.href.match(/^[^\\?]*pdf$/i)) {&lt;br /&gt;
 			var sFilename = elmLink.href.match(/[^\/]+pdf$/i); &lt;br /&gt;
 			elmLink.addEventListener('click', function(event) {&lt;br /&gt;
 				if (!window.confirm('Are you sure you want to ' + &lt;br /&gt;
 						'open the PDF file &amp;quot;' + &lt;br /&gt;
 						sFilename + '&amp;quot;?')) {&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 						event.stopPropagation();&lt;br /&gt;
 						event.preventDefault();&lt;br /&gt;
 				}&lt;br /&gt;
 			}, true);&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
&lt;br /&gt;
=== Running the Hack ===&lt;br /&gt;
&lt;br /&gt;
After installing the user script (Tools → Install This User Script), go to ''http://www.google.com'' and search for census &amp;lt;tt&amp;gt;filetype:pdf&amp;lt;/tt&amp;gt;. At the time of this writing, the first search result is a link to a PDF file titled &amp;quot;Income, Poverty, and Health Insurance Coverage in the United States.&amp;quot; Click the link, and Firefox will pop up a warning dialog asking you to confirm opening the PDF, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-9|Figure 2-9]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-9&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-9. PDF confirmation dialog'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt110.png|PDF confirmation dialog]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you click OK, the link will open, Firefox will launch the Adobe Acrobat plug-in, and you will see the PDF without further interruption. If you click Cancel, you'll stay on the search results page, where you can click &amp;quot;View as HTML&amp;quot; to see Google's version of the PDF file converted to HTML.&lt;br /&gt;
&lt;br /&gt;
== Avoid the Slashdot Effect ==&lt;br /&gt;
&lt;br /&gt;
'''Add web cache links to Slashdot articles'''.&lt;br /&gt;
&lt;br /&gt;
Reading Slashdot is one of my guilty pleasures. It is a guilty pleasure that I share with tens of thousands of other tech geeks. People who have been linked from a Slashdot article report that Slashdot sends as many as 100,000 visitors to their site within 24 hours. Many sites cannot handle this amount of traffic. In fact, the situation of having your server crash after being linked from Slashdot is known as ''the Slashdot effect''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tip&amp;quot;&amp;gt;&lt;br /&gt;
'''Tip'''&lt;br /&gt;
&lt;br /&gt;
Read more about the Slashdot effect at ''http://en.wikipedia.org/wiki/Slashdot_effect''.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This hack tries to mitigate the Slashdot effect by adding links to Slashdot articles that point to various global web caching systems. Instead of visiting the linked site, you can view the same page through a third-party proxy. If the Slashdot effect has already taken hold, the linked page might still be available in one of these caches.&lt;br /&gt;
&lt;br /&gt;
=== The Code ===&lt;br /&gt;
&lt;br /&gt;
This user script runs on all Slashdot pages, including the home page. The script adds a number of CSS rules to the page to style the links we're about to add. Then, it constructs three new links—one to Coral Cache, one to MirrorDot, and one to the Google Cache—and adds them after each external link in the Slashdot article.&lt;br /&gt;
&lt;br /&gt;
Save the following user script as ''slashdotcache.user.js'':&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	// ==UserScript==&lt;br /&gt;
	// @name        Slashdot Cache&lt;br /&gt;
	// @namespace   http://www.cs.uni-magdeburg.de/~vlaube/Projekte/&lt;br /&gt;
	GreaseMonkey/&lt;br /&gt;
	// @description Adds links to web caches on Slashdot&lt;br /&gt;
	// @include     http://slashdot.tld/*&lt;br /&gt;
	// @include     http://*.slashdot.tld/*&lt;br /&gt;
	// ==/UserScript==&lt;br /&gt;
&lt;br /&gt;
	// based on code by Valentin Laube&lt;br /&gt;
	// and included here with his gracious permission&lt;br /&gt;
&lt;br /&gt;
	var coralcacheicon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA'+ &lt;br /&gt;
	'oAAAAKCAYAAACNMs%2B9AAAAgUlEQVQY042O0QnCQBQEZy0sFiEkVVxa8GxAuLOLgD3cV'+ &lt;br /&gt;
	'RKwAytYf05JkGgGFt7H8nZkG10UgBNwZE0F7j77JiIJGPlNFhGzgwOQd%2FQytrEJdjtb'+ &lt;br /&gt;
	'rs%2FORAqRZBvZBrQxby2nv5iHniqokquUgM%2FH8Hadh57HNG05rlMgFXDL0vE%2FL%2'+ &lt;br /&gt;
	'BEXVN83HSenAAAAAElFTkSuQmCC'; &lt;br /&gt;
&lt;br /&gt;
	var mirrordoticon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAo'+ &lt;br /&gt;
	'AAAAKCAYAAACNMs%2B9AAAAbklEQVQY05WQMRKEMAwDNzzqUobWv%2BBedvcK3EKZV4km'+ &lt;br /&gt;
	'BiYFE9RYI3mssZIkRjD1Qnbfsvv2uJjdF6AApfELkpDEZ12XmHcefpJEiyrAF%2Fi1G8H'+ &lt;br /&gt;
	'3ajZPjOJVdPfMGV3N%2FuGlvseopprNdz2NFn4AFndcO4mmiYkAAAAASUVORK5CYII%3D'; &lt;br /&gt;
	var googleicon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAA'+ &lt;br /&gt;
	'AKCAIAAAACUFjqAAAAiklEQVQY02MUjfmmFxPFgAuIxnz7jwNcU9BngSjae%2FbDxJUPj'+ &lt;br /&gt;
	'1z%2BxMDAYKPLlx8u72wswMDAwASRnrjyIQMDw%2BoW3XfbbfPD5SFchOGCHof2nHmPaT'+ &lt;br /&gt;
	'gTpmuEPA8LeR6GsKHSNrp8E1c%2B3Hv2A8QKG10%2BiDjUaRD7Qmsuw51GlMcYnXcE4Aq'+ &lt;br /&gt;
	'SyRn3Abz4culPbiCuAAAAAElFTkSuQmCC'; &lt;br /&gt;
	var backgroundimage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA'+ &lt;br /&gt;
	'DEAAAAOCAYAAACGsPRkAAAAHXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBUaGUgR0lNUO'+ &lt;br /&gt;
	'9kJW4AAAC7SURBVEjH7daxDYMwEEbhh11cAxKSKYEV0qeKMgETZBbPkgmYIEqVPisAJZa'+ &lt;br /&gt;
	'QTOPCUprQZYAY8Sb4P11zGcD9dT0BFuhIpx6wt%2FPjnX0BTxEpjako8uLv1%2FvV49xM'+ &lt;br /&gt;
	'CGEBLgqwIlI2dZsEAKDIC5q6RURKwCqgM6ZCa01Kaa0xpgLo1CZLsW23YgcdiANxIH4g%'+ &lt;br /&gt;
	'2FOqTHL%2FtVkDv3EyMMSlAjBHnZoBeATaEsIzTkMxF%2FOoZp2F7O2y2hwfwA3URQvMn'+ &lt;br /&gt;
	'dliTAAAAAElFTkSuQmCC';&lt;br /&gt;
&lt;br /&gt;
	function addGlobalStyle(css) { &lt;br /&gt;
		var head, style; &lt;br /&gt;
		head = document.getElementsByTagName('head')[0]; &lt;br /&gt;
		if (!head) { return; } &lt;br /&gt;
		style = document.createElement('style'); &lt;br /&gt;
		style.type = 'text/css'; &lt;br /&gt;
		style.innerHTML = css; &lt;br /&gt;
		head.appendChild(style);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	addGlobalStyle('' +&lt;br /&gt;
	'a.coralcacheicon, a.mirrordoticon, a.googleicon { \n' +&lt;br /&gt;
	' padding-left: 15px; background: center no-repeat; \n' +&lt;br /&gt;
	'} \n' +&lt;br /&gt;
	'a.coralcacheicon { \n' +&lt;br /&gt;
	' background-image: url(' +coralcacheicon + '); \n' +&lt;br /&gt;
	'} \n' +&lt;br /&gt;
	'a.mirrordoticon { \n' +&lt;br /&gt;
	' background-image: url(' + mirrordoticon + '); \n' +&lt;br /&gt;
	'} \n' +&lt;br /&gt;
	'a.googleicon { \n' +&lt;br /&gt;
	' background-image: url(' + googleicon + '); \n' +&lt;br /&gt;
	'} \n' +&lt;br /&gt;
	'a.coralcacheicon:hover, a.mirrordoticon:hover, ' +&lt;br /&gt;
	'a.googleicon:hover { \n' +&lt;br /&gt;
	' opacity: 0.5; \n' +&lt;br /&gt;
	'} \n' +&lt;br /&gt;
	'div.backgroundimage { \n' +&lt;br /&gt;
	'  display:inline; \n' +&lt;br /&gt;
	'  white-space: nowrap; \n' +&lt;br /&gt;
	'  padding:3px; \n' +&lt;br /&gt;
	'  background:url(' +  backgroundimage + ') center no-repeat; \n' +&lt;br /&gt;
	'}');&lt;br /&gt;
&lt;br /&gt;
	var link, anchor, background;&lt;br /&gt;
	for (var i=0; i&amp;lt;document.&amp;lt;/nowiki&amp;gt;linkslinks.length; i++) {&lt;br /&gt;
 &lt;br /&gt;
 	link = document.links&amp;lt;nowiki&amp;gt;links[i];&lt;br /&gt;
&lt;br /&gt;
	// filter relative links&lt;br /&gt;
	if(link.getAttribute('href').substring(0,7) != 'http://') {&lt;br /&gt;
		continue;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// filter all other links    &lt;br /&gt;
	if(link.parentNode.nodeName.toLowerCase() != 'i' &amp;amp;&amp;amp;       &lt;br /&gt;
       (link.parentNode.nodeName.toLowerCase() != 'font' || &lt;br /&gt;
	   link.parentNode.color != '#000000' || link.parentNode.size == '2') &lt;br /&gt;
&amp;amp;&amp;amp;&lt;br /&gt;
	   (!link.nextSibling || !link.nextSibling.nodeValue ||&lt;br /&gt;
	   link.nextSibling.nodeValue.charAt(1) != '[')) {&lt;br /&gt;
	   continue;&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// add background&lt;br /&gt;
	background = document.createElement('div');&lt;br /&gt;
	background.className = 'backgroundimage';&lt;br /&gt;
	link.parentNode.insertBefore(background, link.nextSibling);&lt;br /&gt;
&lt;br /&gt;
	//add mirrordot link&lt;br /&gt;
	anchor = document.createElement('a');&lt;br /&gt;
	anchor.href = 'http://www.mirrordot.com/find-mirror.html?' + link.href;&lt;br /&gt;
	anchor.title = 'MirrorDot - Solving the &amp;lt;/nowiki&amp;gt;Slashdot effect&amp;lt;nowiki&amp;gt;Slashdot Effect';&lt;br /&gt;
	anchor.className = 'mirrordoticon';&lt;br /&gt;
	background.appendChild(anchor);&lt;br /&gt;
&lt;br /&gt;
	//add coral cache link&lt;br /&gt;
	anchor = document.createElement('a');&lt;br /&gt;
	anchor.href = link.href;&lt;br /&gt;
	anchor.host += '.nyud.net:8090';&lt;br /&gt;
	anchor.title = 'Coral - The NYU Distribution Network';&lt;br /&gt;
	anchor.className = 'coralcacheicon';&lt;br /&gt;
	background.appendChild(anchor);&lt;br /&gt;
&lt;br /&gt;
	//add google cache link&lt;br /&gt;
	anchor = document.createElement('a');&lt;br /&gt;
	anchor.href = 'http://www.google.com/search?q=cache:' + link.href;&lt;br /&gt;
	anchor.title = 'Google Cache';&lt;br /&gt;
	anchor.className = 'googleicon';&lt;br /&gt;
	background.appendChild(anchor);&lt;br /&gt;
&lt;br /&gt;
	// add a space so it wraps nicely &lt;br /&gt;
	link.parentNode.insertBefore(document.createTextNode(' '), &lt;br /&gt;
		link.nextSibling);&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Running the Hack ===&lt;br /&gt;
&lt;br /&gt;
After installing the user script (Tools → Install This User Script), go to ''http://slashdot.org''. In the summary of each article, you will see a set of small icons next to each link, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-10|Figure 2-10]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-10&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-10. Slashdot cache links'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt112.png|Slashdot cache links]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first icon points to the MirrorDot cache for the linked page, the second icon points to the Coral Cache version of the link, and the third points to the Google Cache version. If the linked page is unavailable because of the Slashdot effect, you can click any of the cache links to attempt to view the link. For example, the MirrorDot link takes you to a page on MirrorDot (''http://www.mirrordot.com'') that looks like [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-11|Figure 2-11]].&lt;br /&gt;
&lt;br /&gt;
The Coral Cache system works ''on demand'': the page is not cached until someone requests it. MirrorDot works by polling Slashdot frequently to find new links before the Slashdot effect takes the linked site down. Google Cache works in conjunction with Google's standard web crawlers, so brand-new pages might not be available in the Google Cache if Google had not indexed them before they appeared on Slashdot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-11&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-11. MirrorDot cache of Slashdotted link'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt113.png|MirrorDot cache of Slashdotted link]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Convert UPS and FedEx Tracking Numbers to Links ==&lt;br /&gt;
&lt;br /&gt;
'''Make it easier to track packages'''.&lt;br /&gt;
&lt;br /&gt;
All major package-delivery companies have web sites that allow you to track the status of packages. This is especially useful for online shoppers. Unless you're buying downloadable software, pretty much everything you buy online needs to be shipped one way or another. Unfortunately, not all online retailers are as web-savvy as one might hope.&lt;br /&gt;
&lt;br /&gt;
This hack scans web pages for package tracking numbers and then converts them to links that point to the page on the delivery company's web site that shows the shipment's current status.&lt;br /&gt;
&lt;br /&gt;
=== The Code ===&lt;br /&gt;
&lt;br /&gt;
This user script runs on all pages. It is similar to &amp;quot;Turn Naked URLs into Hyperlinks&amp;quot; [[Greasemonkey Hacks/Linkmania!#Turn Naked URLs into Hyperlinks|'''[Hack #13]''']]. It scans the page for variations of package numbers that are not already contained in an &amp;lt;tt&amp;gt;&amp;lt;a&amp;gt;&amp;lt;/tt&amp;gt; element and then constructs a link that points to the appropriate online tracking site.&lt;br /&gt;
&lt;br /&gt;
These patterns are converted into links to UPS (''http://www.ups.com'' ):&lt;br /&gt;
&lt;br /&gt;
* 1Z 999 999 99 9999 999 9&lt;br /&gt;
* 9999 9999 999&lt;br /&gt;
* T999 9999 999&lt;br /&gt;
&lt;br /&gt;
This pattern is converted into a link to FedEx (''http://www.fedex.com''):&lt;br /&gt;
&lt;br /&gt;
* 9999 9999 9999&lt;br /&gt;
&lt;br /&gt;
The following patterns are converted into links to the United States Postal Service (''http://www.usps.com'' ):&lt;br /&gt;
&lt;br /&gt;
* 9999 9999 9999 9999 9999 99&lt;br /&gt;
* 9999 9999 9999 9999 9999&lt;br /&gt;
&lt;br /&gt;
Save the following user script as ''tracking-linkify.user.js'':&lt;br /&gt;
&lt;br /&gt;
 	// ==UserScript==&lt;br /&gt;
 	// @name UPS/FedEx tracking numbers&amp;lt;nowiki&amp;gt;FedEx Tracking Linkify&lt;br /&gt;
	// @namespace http://scripts.slightlyinsane.com&lt;br /&gt;
	// @description Link package &amp;lt;/nowiki&amp;gt;tracking numbers&amp;lt;nowiki&amp;gt;tracking numbers to appropriate site&lt;br /&gt;
	// @include *&lt;br /&gt;
	// ==/UserScript==&lt;br /&gt;
&lt;br /&gt;
	// Based on code by Justin Novack and Logan Ingalls&lt;br /&gt;
	// and included here with their gracious permission&lt;br /&gt;
	// Originally licensed under a Create Commons license&lt;br /&gt;
	// Visit http://creativecommons.org/licenses/by-sa/2.0/ for details&lt;br /&gt;
&lt;br /&gt;
	var UPSRegex = new RegExp('/\b(1Z ?[0-9A-Z]{3} ?[0-9A-Z]{3} ?[0-9A-Z]{'+&lt;br /&gt;
	'2} ?[0-9A-Z]{4} ?[0-9A-Z]{3} ?[0-9A-Z]|[\\dT]\\d\\d\\d ?\\d\\d\\d\\d '+&lt;br /&gt;
	'?\\d\\d\\d)\\b', 'ig');&lt;br /&gt;
	var FEXRegex = new RegExp('\\b(\\d\\d\\d\\d ?\\d\\d\\d\\d ?\\d\\d\\d\\'+&lt;br /&gt;
	'd)\\b', 'ig');&lt;br /&gt;
	var USARegex = new RegExp('\\b(\\d\\d\\d\\d ?\\d\\d\\d\\d ?\\d\\d\\d\\'+&lt;br /&gt;
	'd ?\\d\\d\\d\\d ?\\d\\d\\d\\d ?\\d\\d|\\d\\d\\d\\d ?\\d\\d\\d\\d ?\\d'+&lt;br /&gt;
	'\\d\\d\\d ?\\d\\d\\d\\d ?\\d\\d\\d\\d)\\b', 'ig');&lt;br /&gt;
&lt;br /&gt;
	function UPSUrl(t) {&lt;br /&gt;
		return 'http://wwwapps.ups.com/WebTracking/processInputRequest?sor'+&lt;br /&gt;
			't_by=status&amp;amp;tracknums_displayed=1&amp;amp;TypeOfInquiryNumber=T&amp;amp;loc=e'+&lt;br /&gt;
			'n_US&amp;amp;InquiryNumber1=' + String(t).replace(/ /g, '') +&lt;br /&gt;
			'&amp;amp;track.x=0&amp;amp;track.y=0';&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function FEXUrl(t) {&lt;br /&gt;
		return 'http://www.fedex.com/cgi-bin/tracking?action=track&amp;amp;languag'+&lt;br /&gt;
			'e=english&amp;amp;cntry_code=us&amp;amp;initial=x&amp;amp;tracknumbers=' +&lt;br /&gt;
			String(t).replace(/ /g, '');&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function USAUrl(t) {&lt;br /&gt;
	return 'http://trkcnfrm1.smi.usps.com/netdata-cgi/db2www/cbd_243.d'+&lt;br /&gt;
&lt;br /&gt;
		'2w/output?CAMEFROM=OK&amp;amp;strOrigTrackNum=' +&lt;br /&gt;
		String(t).replace(/ /g, '');&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// tags we will scan looking for un-hyperlinked urls&lt;br /&gt;
	var allowedParents = [&lt;br /&gt;
		'abbr', 'acronym', 'address', 'applet', 'b', 'bdo', 'big',&lt;br /&gt;
		'blockquote', 'body', 'caption', 'center', 'cite', 'code',&lt;br /&gt;
		'dd', 'del', 'div', 'dfn', 'dt', 'em', 'fieldset', 'font',&lt;br /&gt;
		'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'i', 'iframe',&lt;br /&gt;
		'ins', 'kdb', 'li', 'object', 'pre', 'p', 'q', 'samp',&lt;br /&gt;
		'small', 'span', 'strike', 's', 'strong', 'sub', 'sup',&lt;br /&gt;
		'td', 'th', 'tt', 'u', 'var'];&lt;br /&gt;
&lt;br /&gt;
	var xpath = '//text()[(parent::' + allowedParents.join(' or parent::') +&lt;br /&gt;
		')]';&lt;br /&gt;
&lt;br /&gt;
	var candidates = document.evaluate(xpath, document, null,&lt;br /&gt;
		XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);&lt;br /&gt;
&lt;br /&gt;
	//var tO = new Date().getTime();&lt;br /&gt;
	for (var cand = null, i = 0; (cand = candidates.snapshotItem(i)); i++) {&lt;br /&gt;
&lt;br /&gt;
	// &amp;lt;/nowiki&amp;gt;UPS tracking numbersUPS Track&lt;br /&gt;
 	if (linksUPS and FedEx tracking numbersUPSRegex.test(cand.nodeValue)) {&lt;br /&gt;
 		var span = document.createElement('span');&lt;br /&gt;
 		var source = cand.nodeValue;&lt;br /&gt;
 &lt;br /&gt;
 		cand.parentNode.replaceChild(span, cand);&lt;br /&gt;
 	&lt;br /&gt;
 		UPSRegex.lastIndex = 0;&lt;br /&gt;
 		for (var match = null, lastLastIndex = 0;&lt;br /&gt;
 			 (match = UPSRegex.exec(source)); ) {&lt;br /&gt;
 			span.appendChild(document.createTextNode(&lt;br /&gt;
 				source.substring(lastLastIndex, match.index)));&lt;br /&gt;
 &lt;br /&gt;
 			var a = document.createElement('a');&lt;br /&gt;
 			a.setAttribute('href', UPSUrl(match[0]));&lt;br /&gt;
 			a.setAttribute('title', 'Linkified to UPS');&lt;br /&gt;
 			a.appendChild(document.createTextNode(match[0]));&lt;br /&gt;
 			span.appendChild(a);&lt;br /&gt;
 &lt;br /&gt;
 			lastLastIndex = UPSRegex.lastIndex;&lt;br /&gt;
 		}&lt;br /&gt;
 		&lt;br /&gt;
 		span.appendChild(document.createTextNode(&lt;br /&gt;
 			source.substring(lastLastIndex)));&lt;br /&gt;
 		span.normalize();&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	// USPS Track&lt;br /&gt;
 	if (USARegex.test(cand.nodeValue)) {&lt;br /&gt;
 		var span = document.createElement('span');&lt;br /&gt;
 &lt;br /&gt;
 		var source = linksUPS and FedEx tracking numberscand.nodeValue;&lt;br /&gt;
 		&lt;br /&gt;
 		cand.parentNode.replaceChild(span, cand);&lt;br /&gt;
 &lt;br /&gt;
 		USARegex.lastIndex = 0;&lt;br /&gt;
 		for (var match = null, lastLastIndex = 0;&lt;br /&gt;
 			 (match = USARegex.exec(source)); ) {&lt;br /&gt;
 			span.appendChild(document.createTextNode(&lt;br /&gt;
 				source.substring(lastLastIndex, match.index)));&lt;br /&gt;
 &lt;br /&gt;
 			var a = document.createElement('a');&lt;br /&gt;
 			a.setAttribute('href', USAUrl(match[0]));&lt;br /&gt;
 			a.setAttribute('title', 'Linkified to USPS');&lt;br /&gt;
 			a.appendChild(document.createTextNode(match[0]));&lt;br /&gt;
 			span.appendChild(a);&lt;br /&gt;
 &lt;br /&gt;
 			lastLastIndex = USARegex.lastIndex;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		span.appendChild(document.createTextNode(&lt;br /&gt;
 			source.substring(lastLastIndex)));&lt;br /&gt;
 		span.normalize();&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	// FedEx tracking numbersFedEx Track&lt;br /&gt;
 	if (FEXRegex.test(cand.nodeValue)) {&lt;br /&gt;
 		var span = document.createElement('span');&lt;br /&gt;
 		var source = cand.nodeValue;&lt;br /&gt;
 &lt;br /&gt;
 		cand.parentNode.replaceChild(span, cand);&lt;br /&gt;
 &lt;br /&gt;
 		FEXRegex.lastIndex = 0;&lt;br /&gt;
 		for (var match = null, lastLastIndex = 0;&lt;br /&gt;
 			 (match = FEXRegex.exec(source)); ) {&lt;br /&gt;
 			span.appendChild(document.createTextNode(&lt;br /&gt;
 				source.substring(lastLastIndex, match.index)));&lt;br /&gt;
 &lt;br /&gt;
 			var a = document.createElement('a');&lt;br /&gt;
 			a.setAttribute('href', FEXUrl(match[0]));&lt;br /&gt;
 			a.setAttribute('title', 'Linkified to FedEx');&lt;br /&gt;
 			a.appendChild(document.createTextNode(match[0]));&lt;br /&gt;
 			span.appendChild(a);&lt;br /&gt;
 &lt;br /&gt;
 			lastLastIndex = FEXRegex.lastIndex;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		span.appendChild(document.createTextNode(&lt;br /&gt;
 			source.substring(lastLastIndex)));&lt;br /&gt;
 		span.normalize();&lt;br /&gt;
 	}&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
=== Running the Hack ===&lt;br /&gt;
&lt;br /&gt;
Before installing the script, create a file called ''testlinkify.html'' with the following contents:&lt;br /&gt;
&lt;br /&gt;
 	&amp;lt;html&amp;gt;&lt;br /&gt;
 	&amp;lt;head&amp;gt;&lt;br /&gt;
 	&amp;lt;title&amp;gt;Test Linkify&amp;lt;/title&amp;gt;&lt;br /&gt;
 	&amp;lt;/head&amp;gt;&lt;br /&gt;
 	&amp;lt;body&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;p&amp;gt;UPS tracking numbersUPS tracking numberstracking numbers:&amp;amp;lt;/p&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;ul&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;li&amp;gt;Package 1Z 999 999 99 9999 999 9 sent&amp;amp;lt;/li&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;li&amp;gt;Package 9999 9999 999 sent &amp;amp;lt;/li&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;li&amp;gt;Package T999 9999 999 sent&amp;amp;lt;/li&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;/ul&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;p&amp;gt;FedEx tracking numbersFedEx tracking numbers:&amp;amp;lt;/p&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;ul&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;li&amp;gt;Package 9999 9999 9999 sent&amp;amp;lt;/li&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;/ul&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;p&amp;gt;USPS tracking numbers:&amp;amp;lt;/p&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;ul&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;li&amp;gt;Package 9999 9999 9999 9999 9999 99 sent&amp;amp;lt;/li&amp;gt;&lt;br /&gt;
 	&amp;amp;lt;/ul&amp;gt;&lt;br /&gt;
 	&amp;lt;/body&amp;gt;&lt;br /&gt;
 	&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save the file and open it in Firefox (File → Open…). It lists a number of variations of (fake) package tracking numbers in plain text, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-12|Figure 2-12]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-12&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-12. Package tracking numbers'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt116.png|Package tracking numbers]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, install the user script (Tools → Install This User Script), and refresh the test page. The script has converted the package tracking numbers to links to their respective online tracking sites, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-13|Figure 2-13]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-13&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-13. Package tracking links'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt117.png|Package tracking links]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you hover over a link, you will see a tool tip that lets you know that the tracking number was automatically converted to a link.&lt;br /&gt;
&lt;br /&gt;
== Follow Links Without Clicking Them ==&lt;br /&gt;
&lt;br /&gt;
'''Hover over any link for a short time to open it in a new tab in the background'''.&lt;br /&gt;
&lt;br /&gt;
This hack was inspired by dontclick.it (''http://dontclick.it''), a site that demonstrates some user interaction techniques that don't involve clicking. The site is written in Flash, which annoys me, but it gave me the idea of ''lazy clicking'': the ability to open links just by moving the cursor over the link and leaving it there for a short time. I don't claim that it will cure your carpal tunnel syndrome, but it has changed the way I browse the Web.&lt;br /&gt;
&lt;br /&gt;
=== The Code ===&lt;br /&gt;
&lt;br /&gt;
This user script runs on nonsecure web pages. By default, it will not run on secure web pages, because it has been my experience that most secure sites, such as online banking sites, are very unweblike and don't support opening links in new tabs.&lt;br /&gt;
&lt;br /&gt;
The script gets a list of all the links (which Firefox helpfully maintains for us in the &amp;lt;tt&amp;gt;document.links&amp;lt;/tt&amp;gt; collection) and attaches three event handlers to each link:&lt;br /&gt;
&lt;br /&gt;
;Mouseover&lt;br /&gt;
: When you move your cursor to a link, the script starts a timer that lasts for 1.5 seconds (1500 milliseconds). When the timer runs down, it calls &amp;lt;tt&amp;gt;GM_openInTab&amp;lt;/tt&amp;gt; to open the link in a new tab.&lt;br /&gt;
;Mouseout&lt;br /&gt;
: If you move your cursor off a link within 1.5 seconds, the onmouseout event handler cancels the timer, so the link will not open.&lt;br /&gt;
;Click&lt;br /&gt;
: If you actually click a link within 1.5 seconds, the &amp;lt;tt&amp;gt;onclick&amp;lt;/tt&amp;gt; event handler cancels the timer and removes all three event handlers. (Note that you can click a link without leaving the page; for example, holding down the Ctrl key while clicking will open the link in a new tab.) This means that if you manually follow a link, the auto-open behavior disappears and the link will not open twice.&lt;br /&gt;
&lt;br /&gt;
Save the following user script as ''autoclick.user.js'':&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	// ==UserScript==&lt;br /&gt;
	// @name AutoClick&lt;br /&gt;
	// @namespace http://diveintomark.org/projects/greasemonkey/&lt;br /&gt;
	// @description hover over &amp;lt;/nowiki&amp;gt;links&amp;lt;nowiki&amp;gt;links for 1.5 seconds to open in a new tab&lt;br /&gt;
	// @include http://*&lt;br /&gt;
	// ==/UserScript==&lt;br /&gt;
&lt;br /&gt;
	var _clickTarget = null;&lt;br /&gt;
	var _autoClickTimeoutID = null;&lt;br /&gt;
&lt;br /&gt;
	function mouseover(event) {&lt;br /&gt;
		_clickTarget = event.currentTarget;&lt;br /&gt;
		_autoclickTimeoutID = window.setTimeout(autoclick, 1500);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function mouseout(event) {&lt;br /&gt;
		_clickTarget = null;&lt;br /&gt;
		if (_autoclickTimeoutID) {&lt;br /&gt;
			window.clearTimeout(_autoclickTimeoutID);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function clear(elmLink) {&lt;br /&gt;
		if (!elmLink) { return; }&lt;br /&gt;
		elmLink.removeEventListener('mouseover', mouseover, true);&lt;br /&gt;
		elmLink.removeEventListener('mouseout', mouseout, true);&lt;br /&gt;
		elmLink.removeEventListener('click', click, true);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function click(event) {&lt;br /&gt;
		var elmLink = event.currentTarget;&lt;br /&gt;
		if (!elmLink) { return false; }&lt;br /&gt;
		clear(elmLink);&lt;br /&gt;
		mouseout(event);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function autoclick() {&lt;br /&gt;
		if (!_clickTarget) { return; }&lt;br /&gt;
&lt;br /&gt;
		GM_openInTab(_clickTarget.href);&lt;br /&gt;
		clear(_clickTarget);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (var i = document.&amp;lt;/nowiki&amp;gt;linkslinks.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
 		var elmLink = document.links[i];&lt;br /&gt;
 		if (elmLink.href &amp;amp;&amp;amp; elmLink.href.indexOf('javascript:') == -1) {&lt;br /&gt;
 			elmLink.addEventListener('mouseover', mouseover, true);&lt;br /&gt;
 			elmLink.addEventListener('mouseout', mouseout, true);&lt;br /&gt;
 			elmLink.addEventListener('click', click, true);&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
&lt;br /&gt;
=== Running the Hack ===&lt;br /&gt;
&lt;br /&gt;
Before running this hack, you'll need to set up Firefox so that it doesn't bring new tabs to the front. Go to Tools → Options → Advanced. Under Tabbed Browsing, make sure &amp;quot;Select new tabs opened from links&amp;quot; is not checked, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-14|Figure 2-14]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-14&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-14. Firefox tab options'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt119.png|Firefox tab options]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, install the user script (Tools → Install This User Script), and go to ''http://del.icio.us/popular/''. Hover over any link for a short time (1.5 seconds to be precise), and the link will open in a new tab in the background, as shown in [[Greasemonkey Hacks/Linkmania!#greasemonkeyhks-CHP-2-FIG-15|Figure 2-15]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;greasemonkeyhks-CHP-2-FIG-15&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 2-15. Auto-opened link'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Greasemonkey Hacks_I_2_tt120.png|Auto-opened link]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is smart enough not to reopen links you've already opened. If you move your cursor away from the link you just opened, then move it back to the link, it will not open a second time.&lt;br /&gt;
&lt;br /&gt;
The script is also smart enough not to auto-open links you've already clicked. If you move to another link and click while holding down the Ctrl key (or the Command key on Mac OS X), Firefox will open the link in a new tab in the background. If you move away from the link and then move back, it will not auto-open no matter how long you hover over it.&lt;/div&gt;</summary>
		<author><name>Docbook2Wiki</name></author>	</entry>

	</feed>