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 handler that 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 (jQuery not included for legal reasons).

Most internet services are valuable to us because they can add value to our personal information. Google can deliver more relevant search results by monitoring which search results we click on and then tailoring future results to our preferences. FaceBook asks us for some personal information like geographic location and our immediate network of friends, in return they let us connect with new friends and contacts that we wouldn’t have found otherwise. In both cases, these companies are using our personal information to provide a service we find beneficial.

What concerns most people is what else companies do with our information when we’re not using it. Do they use it to spam our friends? Do they monitor our internet behavior and share it with other companies? In truth, most people don’t mind companies keeping track of our data for us—but when they try to monetize that data we begin to feel uncomfortable.

Whenever companies distribute software, as the owner of software, they can place strict legal limitations on what can be done with it. They can say who can use it, in what way, and for how long. Why can’t we, the consumer, place the same limitations on our own information that we let companies use? We should be setting the terms upon which they use our data.

It’s a bit of a role reversal that might take some getting used to but, when it comes to social media, the consumer’s data is the real currency companies value. Why should we have to read a 50-page TOS that tells us how the company is going to use our data? It’s ours.

I would love to see an organization like Creative Commons come out with a personal profile license that companies have to adhere to. There could be a couple flavors, letting us pick the types of activities we’re comfortable with. Maybe we don’t mind our consumer behavior being tracked. (You could get better ads that way.) Maybe we’re cool with email blasts. (Coupons in your inbox?) Or maybe we’re like Steve Gibson and would just assume the company not even be able to decrypt our data on their own servers.

I’m sure this would be a huge pain for companies to keep track of—especially if the number of profile licenses in the wild got above 4 or 5. But companies could tell us to take a hike if they don’t like the type of profile license we’ve chosen. That’s fine with me. There are other fish in the sea. At least this way everything’s up front and both parties know what they’re getting into.

It’s our data. They want to make money off of it. It’s about time we set some terms of use.

Update: With the release of Zend_Layout, the need to this sort of workaround has diminished.

It’s no secret that I’m a big fan of the Zend Framework. After fumbling around with a primitive MVC application at work, I was instantly won over by the clean, and intuitive way they implement MVC. Round about version 0.9, the ViewRenderer was introduced. ViewRenderer is, I’d say, 90% useful. It makes certain assumptions about the way you’re using the framework. If you color between the lines it’s a great help.

One thing I almost always have to do is override the way it selects and automatically renders templates based on controller and action names. I typically roll with a single template and load elements into that template. Of course, I could just disable ViewRenderer altogether, but it does do a lot of other things that I find helpful, like initializing the View.

My solution: extend the default Zend_Controller_Action class. There’s only a few things to do:

  1. Disable the auto-render functionality of ViewRenderer
  2. Add a new $_template property to hold the template to render
  3. Render a single template in the postDispatch method

Here’s the code:

require_once "Zend/Controller/Action.php";

class Blink_Controller_Action extends Zend_Controller_Action
{
    protected $_template = "defaultTemplate.phtml";

    public function init()
    {
        $this->_helper->viewRenderer->setNoRender(true);
        parent::init();
    }

    public function postDispatch()
    {
        echo $this->view->render($this->_template);
    }
}

With our new controller action, we can then largely forget about rendering the View. All we have to do is assign values to the View:

require_once "Blink/Controller/Action.php";

class MyController extends Blink_Controller_Action
{
    public function IndexAction ()
    {
        $this->view->myValue = "some value";
        // Assign more values...
        // Do business logic...

        // Optionally, select a new template to render
        $this->_template = "differentTemplate.phtml";
    }
}
Posted in php | 1 Comment »

As a casual observer of the Web 2.0 boom and fizzle, I’m left to wonder if the Internet as we know it is as mature as we all think it is. However you slice it, the Internet still utilizes the same metaphor as notepad: a page. Don’t get me wrong, I don’t have anything against pages—working for a newspaper, pages keep me employed. But you have to wonder if a page is really the peak of innovation or if maybe we could come up with something better.

Does it make sense to load GMail on a page? Sure, I’m reading my email, but GMail is a full-fledged web application. I’ve never heard it called a “web page”. My newspaper can’t automatically mark the sports section as read or filter out all the unwanted ads tucked in between stories. It just sits there. Many web applications, like GMail, Yahoo! Mail, and BaseCamp, have been painstakingly built on top of this page metaphor—not necessarily because it’s the best platform for building web applications, but because the delivery mechanism is so prolific.

The changes have been slow and incremental, but there has been a steady push away from the original concept of a web page. Macromedia, er, Adobe has made tons of money with Flash. The Web 2.0 craze brought us AJAX. Java applets run on countless intranets worldwide (thankfully, less are being seen in the wild). Adobe, Apple, Microsoft, and many other companies all have plugins that let you watch video on a web page. All of these things are great examples of innovation, but if you look a little closer, they all share another common trait. Each one seeks to add a feature or some new functionality that was not part of the original page metaphor.

It’s getting crowded in the browser. Plugins are great; I love ‘em. But when you need all these extra applications running inside your web page, you have to wonder if we’re just polishing a rusty relic. Perhaps the Page has run its course and we should be looking for its successor, whatever that may be. Or perhaps we’re entering an age where the metaphor doesn’t matter. Have people become so acclimated to computer technology that tried and true metaphors like the desktop and folders are loosing their cachet? When a web page isn’t a page at all, is anything lost?

Posted in Innovation | 1 Comment »

Code FaceAfter a few posts where I wanted to include code examples, I quickly became frustrated with the standard <pre> display that the folks at WordPress recommend. I looked for a plugin that worked well, but didn’t like what I was seeing. So at the prodding of my colleague, Pat Doran, I decided to roll my own plugin.

The result is my “Code Face” plugin. It uses the YUI JavaScript framework to scan your posts and replace specially tagged <pre> blocks with rich code syntax highlighting via the syntaxhighlighter utility. Ninety-nine percent of the plugin is written in JavaScript using the concept of progressive enhancement. That means that even if your readers have JavaScript turned off or are using a screen reader, the content of your post is still highly accessible.

Check it out and let me know what you think. I’d love to hear your comments.

Until about 3 weeks ago, I had almost no idea what “polymorphism” meant—although I knew exactly how to do it. It’s one of those things you’re just going to eventually pick up if you play around with object oriented programming enough, whether you know that’s what it’s called or not. I remember bumping into the term a couple times but the nerd-power behind the lengthy volumes describing it defeated me time and again. Here’s stab at a crude explanation in terms I know I could have understood.

The basic premise of polymorphism, one might argue, can be likened to Plato’s theory of Forms. Plato believed that everything in the world was an imperfect representation of its true Form. A rock on the ground could be thought of as an inexact approximation of its true Form: “Rock”. Likewise, that chair in your room is merely mimicking the perfect, idealized form of a chair. So somewhere—perhaps not in physical form—there exists a pure, perfect, and authoritative version of a chair that all chairs here on Earth mimic, but never quite get 100% right.

It may sound a bit existential, but what Plato was really talking about (from a computer science point of view) was methods of categorization. Think about it. How hard would it be to get a computer to recognize that chair in your room as a chair and not a lamp? By the same token, it’s very easy for us to classify it as a chair. When we classify things on the spot like this, we’re comparing what we see with our own mental vision of what a chair’s “true Form” is.

What is its true Form? What makes a chair a chair, or a door a door? Well, a chair will typically have 3 or more legs, a place to rest your bum, and a back you can lean against. Doors are harder to pin down, but they are generally embedded in walls, and will open somehow to let you go through that wall.

For now, let’s take the example of a door and try to point this ship back towards the topic at hand: polymorphism. Suppose we wanted to build some code to mimic a door. What would it need to do? Ideally it would open. It should probably also be in a wall of some kind. Some basic height and width dimensions might be handy too. So, if I may, this might be your pseudo-code for a door:

door {
action: open();
property: wallType;
property: width;
property: height;
}

What we just pseudo-created is, arguably, the “perfect” Form of a door. Really, we just created a door that’s so generalized it’s pretty much useless. What we really need is an instance of this door, that we can use and go through:

supermarketDoor is-a door {
action: open(
action: slideOpen();
);
property: wallType = “glass”;
property: width = “12 feet”;
property: height = “8 feet”;
}

And that’s it. We just polymorphed. Did you feel it? We can now use our supermarketDoor object. But, from a programming point of view, what allows us to use this door is not that we know how it works. Rather, we can use this door because we know it is a door, and as such has certain characteristics that we know about. We know this door, or any other door for that matter, will be a predicable variation of our original “true Form” of a door. It will open, it will be in a wall of some type, and it will have height and width dimensions. The fact that this door slides open isn’t important, we just want it to open when we tell it to.

So now we can write a quick bit of code that tells a given door to open. And since we know all doors mimic the Form of a door, we can rest assured that our code will always work—no matter what kind of door it’s presented with. This allows us to create a million different types of doors, and never have to touch our original code that opens a door again. That’s the power of polymorphism.

Ever get that annoying “Click to activate and use this control” message in IE when you embed a Flash movie? I did and couldn’t find a solution that worked as well as I’d like. A quick browse of my Google results brought be here, but the solution there was kinda sloppy in my opinion. But with a few tweaks, I got things working…and with the added street cred’ of not introducing a single global variable.

Here’s the code:

(function()
{
    var clear = function(a)
    {
        for(var i=0; i < a.length; i++)
        {
            a[i].outerHTML=a[i].outerHTML;
        }
    };

    clear(document.getElementsByTagName("object"));
    clear(document.getElementsByTagName("embed"));
})();

The original code I found only applied the fix to object tags. But since use of the object tag is becoming deprecated, we also need to touch the embed tags as well. The code above does both and is wrapped in an anonymous function to keep all is private bits private.

Finally, since this is an IE-only fix, we should make use of IE’s conditional comments so other browsers don’t have to be bothered by the script. Assuming we placed (a minified version of) the code into a file named controlFix.js, we then add the following code at the end of the source code:

<!--[if IE]>
<script type="text/javascript" src="controlFix.js"></script>
<![endif]-->

If you’d like to use this on your site, you can download the minified JavaScript here.

On of the best tools around for helping you speed up your page load times is Yahoo!’s YSlow Firefox extension. I’ve been using it for a while and found it has some interesting insights on page load performance. Its recommendations come from Yahoo!’s “Exceptional Performance Team” 14 recommendations for speeding up page load times. If you’d rather hear it right from the horses mouth, have at, otherwise you can watch the conveniently embedded video below.

Briefly, the 14 recommendations are:

  1. Make fewer HTTP requests
  2. Use a CDN (like Akamai)
  3. Add an “Expires” header
  4. Use GZIP compression
  5. Put CSS at the top
  6. Put JavaScript (JS) at the bottom
  7. Avoid CSS expressions
  8. Make JS and CSS external
  9. Reduce DNS lookups
  10. Minify JS
  11. Avoid redirects
  12. Remove duplicate scripts
  13. Configure ETags
  14. Make AJAX cacheable

Since the video can probably explain each of these points better than I can, I’ll let them speak for themselves for the most part. Lately though, I have been thinking a lot about two of them, namely #1 and #10: Make fewer HTTP requests and Minify JavaScript. Bit by bit, I’ve been trying to get all our JavaScript files at work “minified” but, it’s an uphill battle with so many files being edited semi-frequently by people other than myself. Since minified JavaScript is almost impossible to read without getting a headache, you’d have to keep the un-minified versions on tap somewhere and leave step by step instructions on how to minify them and then get them on the site. Having people then copy and paste the minified versions into a single aggregate file is simply asking for trouble.

Then I found a key part of the solution: a port of Crockford’s JSMin to PHP. This PHP version, allows you to do something very powerful that the original JavaScript version did not. Now you can use aggregate and minify all your JavaScript into a single HTTP request by calling a PHP script in your script tag which gathers and minifies all the JavaScript for the page.

So, say you wanted to aggregate and minify the JavaScript for your menu and rich text editor of choice. In your HTML, you might use a script tag like this:

<script type="text/javascript" src="/jsaggmin.php?features=menu/richtexteditor"></script>

On the server, jsaggmin.php would do look something like this:

require "jsmin.php";

foreach (explode("/", $_GET['features']) as $feature)
{

    switch ($feature)
    {
        case "menu":
            echo JSMin::minify(file_get_contents("menu.js"));
            break;

        case "richtexteditor":
            echo JSMin::minify(file_get_contents("rte.js"));
            break;
    }

}

Granted, this isn’t the complete solution, but it’s a leap in the right direction. What is needed next (in addition to a caching mechanism) is a way to run the equivalent of JSLint on the server before the files are minified. As a rule of thumb, if a JavaScript file can’t pass JSLint, it will blow up when minified. So the PHP script would need to verify the JavaScript, and echo it as is if it fails to validate. Otherwise, you’ve just minified and aggregated all the scripts on your page and can focus on the other 12 recommendations.

I wish I could say that getting my site converted over to actual blogging software was my new years resolution, but I’ve always found new years resolutions to be a little lame. Let’s just say I’ve been meaning to make the switch off of Drupal and onto WordPress for a while now and the turn of the calendar seemed as good a time as any.

Let me know what you think. I built this theme from scratch, so if you see anything weird going on let me know.

Posted in PSA | 3 Comments »

© 2008 Donald J Sipe | Powered by WordPress | RSS Feed