djsipe.com | Web Development

We’ve all seen them, links that look like they go somewhere but when you roll your mouse over them you see something like “javascript:popupWindow();” in the status bar instead of a URL. Putting JavaScript into the href of links is just a horrible idea as it severely degrades the accessibility of your site (and ticks off people like me who want to see where they’re about to be taken before they click). But rather than just complain about it, I thought I’d put together some code to help us all avoid this situation all together.

The ideal solution is one that will work for the greatest number of users. Given that, we need a solution that will use unobtrusive JavaScript to enhance a standard HTML page with customizable popup windows—rather than rely solely on JavaScript. Since straight-up HTML supports opening links in new windows by adding a target attribute to the link, we start off with a link that looks like this:

<a href="/popup.html" target="popupWindow" class="popup">Open new window</a>

Using this as a starting point, the next step is to create a simple popup window function that wraps the standard DOM method: window.open().  I use this function to do a few things:

  1. Enforce default parameters rather than depend on the browser’s defaults
  2. Provide defaults that favor greater accessibility, ie: scrollbars and resize
  3. Allow a JavaScript object literal to be used instead of the standard configuration string

Here’s the function:

// Create a namespace for our utilities
var UTIL = UTIL || {};
UTIL.popup = UTIL.popup || {};

/**
 * Open popup window
 *
 * Opens a popup window using as little as a URL. An optional params object can
 * be passed.
 *
 * @param {String} href
 * @param {Object} params
 * @return {WindowObjectReference}
 */
UTIL.popup.open = function (href, params) {
	// Defaults (don't leave it to the browser)
	var defaultParams = {
		"width":       "800",   // Window width
		"height":      "600",   // Window height
		"top":         "0",     // Y offset (in pixels) from top of screen
		"left":        "0",     // X offset (in pixels) from left side of screen
		"directories": "no",    // Show directories/Links bar?
		"location":    "no",    // Show location/address bar?
		"resizeable":  "yes",   // Make the window resizable?
		"menubar":     "no",    // Show the menu bar?
		"toolbar":     "no",    // Show the tool (Back button etc.) bar?
		"scrollbars":  "yes",   // Show scrollbars?
		"status":      "no"     // Show the status bar?
	};

	var windowName = params["windowName"] || "new_window";

	var i, useParams = "";

	// Override defaults with custom values while we construct the params string
	for (i in defaultParams) {
		useParams += (useParams === "") ? "" : ",";
		useParams += i + "=";
		useParams += params[i] || defaultParams[i];
	}

	return window.open(href, windowName, useParams);
};

Admittedly, this part isn’t rocket science and could probably be done in a more elegant way, but it’s needed to really open things up for the next part.  Now we get to the fun stuff.  Using jQuery, we search the document for all links that have a CSS class of “popup”.  For each one we find, we add an onClick handlerthat disables the browser’s default onClick behavior for links and then opens up a popup window using the links href attribute.  Here’s the code:

$(function(){ // Run this code when the document's done loading

    // Apply this code to each link with class="popup"
    $("a.popup").each(function (i){

        // Add an onClick behavior to this link
        $(this).click(function(event) {

            // Prevent the browser's default onClick handler
            event.preventDefault();

            // Grab parameters using jQuery's data() method
            var params = $(this).data("popup") || {};

            // Use the target attribute as the window name
            if ($(this).attr("target")) {
               params.windowName = $(this).attr("target");
            }

            // Pop up the window
            var windowObject = UTIL.popup.open(this.href, params);

            // Save the window object for other code to use
            $(this).data("windowObject", windowObject);
        });
    });
});

One of the great features of jQuery that we utilize here is the data method.  This allows us to attach data to DOM elements without corrupting the HTML with non-standard attributes or tags.  Using jQuery’s ability to locate DOM elements using CSS selectors, we can bind the custom configuration object (used in our new popup function) to the links themselves.  Then, when a link is clicked, it can read it’s popup configuration and pass it to the popup window function.  In this way, we can keep our HTML standards compliant and completely separate from our JavaScript code.

Putting it all together, we can create an HTML page like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
		<title>Popup Window Test</title>
		<script type="text/javascript" src="jquery-1.2.6.pack.js"></script>
		<script type="text/javascript" src="utils.js"></script>
	</head>
	<body>
		<ul>
			<li>
				This link uses defaults:
				<a href="http://google.com" target="google" class="popup">Google.com</a>
			</li>
			<li>
				This link uses custom parameters:
				<a id="custom-popup" href="http://yahoo.com" target="yahoo" class="popup">Yahoo.com</a>
			</li>
		</ul>
		<script type="text/javascript">

			// Add custom pop-up properties to the second link
			$("a#custom-popup").data("popup", {width:400,height:400, top:200, left:200});

		</script>
	</body>
</html>

If you would like to download this example, you can get it here.

Tags: , ,

Posted in Front End, JavaScript 11 Comments »

11 Responses to “Doing Pop-Ups the Right Way with jQuery”

  1. PatD Says:

    That’s some hawt jQuery, sir. I’ve come to embrace its easy-for-designers-like-me-to-use usefulness. Make no mistake I will steal evaluate the possibility of using your code if I ever have to pop up a window.

    Did you check out my badass utilization of jQuery on your unnamed former employer’s homepage?

  2. James Says:

    Hi, I found your blog on this new directory of WordPress Blogs at blackhatbootcamp.com/listofwordpressblogs. I dont know how your blog came up, must have been a typo, i duno. Anyways, I just clicked it and here I am. Your blog looks good. Have a nice day. James.

  3. gary Says:

    Thanks for sharing, I just download and tried the code, it seems no working under ff3 and ie6, nothing pops up but new window tab

  4. DJ Says:

    @gary: Probably didn’t work because jQuery wasn’t in the zip file. I’ve updated the zip with a Google-hosted version of jQuery so it should work for you.

    Best,
    DJ

  5. Adam Says:

    Thanx DJ, this was exactly the unobtrusive solution I was looking for.

    Ever thought of turning it into a jQuery plugin?

  6. Shawn Dalton Says:

    NOTE:
    resizable NOT resizeable
    otherwise the resizing wont work in IE

  7. Alex O Says:

    In addition to changing ‘resizeable’ to ‘resizable’ as Shawn pointed out I also changed the util.js on the window.open to focus on the target window in case it was already opened and hidden:

    wo = window.open(href, windowName, useParams);
    return wo.focus();

  8. DJ Says:

    Thanks for all the great comments. I’m going to try to work them all into an update to my hosted example code. (May even think about turning this into a jQuery plugin.)

  9. Scott Says:

    Nice script … client wanted this exact functionality in a site and I didn’t want to pollute my html with inline js … this solution is perfect … +1 for a plugin.

  10. DJ Says:

    Now officially a jQuery plugin. http://plugins.jquery.com/project/open

    I’ll be working on additional documentation in the days to come.

  11. Ben Says:

    Hi,

    Great code!

    How do I make it a pop-under e.g. so it opens under the current window?

Leave a Reply

© 2012 Donald J. Sipe III | Powered by WordPress | RSS Feed