Fix Broken Pop-up Links





Fix Broken Pop-up Links

Change javascript: pseudo-protocol pop-up windows into normal hyperlinks.

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 javascript: pseudo-protocol to create pop-up windows.

A broken pop up looks like this:


	<a href="javascript:popup('http://youngpup.net/')">go to youngpup.net</a>


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 HRef 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 popup 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 HRef doesn't contain a URL; it contains a random JavaScript statement.

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 onclick handler to a regular hyperlink:


	<a href="http://youngpup.net/" 

           onclick="window.open(this.href); return false;"> 

		 go to youngpup.net 

	</a> 


Using Greasemonkey, we can scan for javascript: links that appear to open pop-up windows and then change them to use an onclick handler instead.

The Code

This user script runs on every page. It loops through every link on the page, looking for javascript: URLs. If the link's href attribute begins with javascript:, the script checks whether it appears to open a pop-up window by looking for something that looks like a URL after the javascript: keyword. Since the overwhelming majority of web authors that use "javascript:" links use them to open pop-up windows, this should not have too many false positives.

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 <a> element to use a normal href attribute and move the JavaScript code to the onclick event handler.

Save the following user script as popupfixer.user.js:


	// ==UserScript==

	// @name           Popup Window Fixer

	// @namespace	   http://youngpup.net/userscripts

	// @description	   Fixes javascript: pseudo-links that popup windows

	// @include        *

	// ==/UserScript==



	const urlRegex = /\b(https?:\/\/[^\s+\"\<\>\'\(\)]+)/ig; 

	var candidates = document.getElementsByTagName("a");



	for (var cand = null, i = 0; (cand = candidates[i]); i++) {

		if (cand.getAttribute("onclick") == null &&        

			cand.href.toLowerCase().indexOf("javascript:") == 0) { 

			var match = cand.href.match(urlRegex); 

			if (!match) { continue; } 

			cand.href = match[0];

		} 

	}


Running the Hack

Before installing the script, create a file called testpopup.html with the following contents:


	<html>

	<head>

	<script type="text/javascript">

	function popup(url) { window.open(url); }

	</script>

	</head>

	<body>

	<a href="javascript:popup('http://youngpup.net/')">Aaron's home page</a>

	</body>

	</html>


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 "Open in new tab," the link fails, because the pop-up function is defined only on the current page, not in the new tab.

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 Figure.

Fixed pop-up link


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.

Hacking the Hack

There are various problems with this code, all stemming from the fact that it is hard to know for sure that a "javascript:" link is supposed to open a pop up. For example, this script cannot detect any of these pop-up links:


	<a href="javascript:popup('foo.html')">

	<a href="javascript:popup('foo/bar/')">

	<a href="javascript:popupHomePage()">


All we can say for sure is that hyperlinks that use the "javascript:" 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.

Save the following user script as popupstyler.user.js:


	var candidates = document.links;

	for (var cand = null, i = 0; (cand = candidates[i]); i++) {

		if (cand.href.toLowerCase().indexOf("javascript:") == 0) {

			with (cand.style) {

				background = "#ddd";

				borderTop = "2px solid white";

				borderLeft = "2px solid white";

				borderRight = "2px solid #999";

				borderBottom = "2px solid #999";

				padding = ".5ex 1ex";

				color = "black";

				textDecoration = "none";

			}

		}

	}


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 "javascript:" link now appears to be a button, as shown in Figure.

Styled pop-up link


There is no complete solution that will work with every possible "javascript:" pop-up link, since there are so many variations of JavaScript code to open a new window. In theory, you could redefine the window.open 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.

Aaron Boodman


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows