Archive for May, 2007 Page 2 of 3



RailsConf 2007 Starts Today!

I won’t be attending today’s tutorial sessions, but I’ll be at the conference starting tomorrow. Check out this Map at Google’s My Maps that someone put together, it has a few more things plotted out than I mentioned in my post about what to do in Portland while at RailsConf, but one small mistake I found that you may want to know about is that the Coffee People listed on the map is closed forever. Unfortunately they sold out to Starbucks and it will be replaced very soon with yet another Starbucks. The only reason I mention this is because coffee == freedom, and if you need your coffee fix and want to avoid Starbucks, you’ll be sorely disappointed when you find a closed down Coffee People.

Check out these places to grab coffee instead:

Google Maps + IE PNG Hack + IE 7 = Maps Asplode

Yesterday I went to show someone Unthirsty on their home PC. Of course their PC was riddled with malware and ran like a 3-legged dog. I groaned when I saw the IE7 icon on their desktop. I had tested the site a bunch of times in IE 6, but when I saw the IE7 icon I realized I had never tested it with Unthirsty. Reluctantly I opened it and typed in unthirsty.com in the address bar…and can you guess what happens next? The map comes up on the page completely blank. Why is it whenever you go to show someone a site you’re proud of, it doesn’t work?

Originally in Unthirsty I added in a great Javascript hack that makes transparent PNGs work in IE6. This worked great in IE 6, but as you now know, it caused some problems in IE7 when using Google Maps, causing the map to be blank upon loading. If I switched to satellite view it worked, then back to the regular view, the map corrected itself. But obviously that’s not the solution I wanted. So I changed this:

  <!--[if gte IE 5.5]>
  <script type="text/javascript" src="/lib/pngfix.js"></script>
  <![endif]-->

To this:

  <!--[if lt IE 7]>
  <script type="text/javascript" src="/lib/pngfix.js"></script>
  <![endif]-->

If you’re not familiar with the weird if gte IE 5.5, it’s Microsoft’s way of letting you tell versions of Internet Explorer to use what’s in between those comment blocks. Here I’m telling it to include the pngfix.js file if the version of IE is greater or equal to 5.5. Since this also includes IE7, I changed it to include it if the IE version is less than 7. Problem solved.

I hope this helps someone that is having the same problem, but at the same time this should be a wake up call to a lot of developers out there. CHECK YOUR SITES IN INTERNET EXPLORER 7! Especially if you made any hacks to accomodate IE 6 flaws.

Large Hit State Menus with Javascript and CSS

A growing trend I have been noticing while developing web sites is the need (or want) to create areas on the page that are clickable. Generally these are areas that contain a headline and a snippet of text, and sometimes an image. I really like the idea of having areas of that page that are clickable because I believe it encourages users to click through right away, and can make those worn out ‘click here’ links obsolete.

Typically these large hit state links are created using images. This is both good and bad. Since it’s an image, we can control how the area looks very easily. But the bad thing is it doesn’t do you any good for accessibility and search engine visibility.

Good hit states should:

  • Allow a user to click anywhere in the area to follow the link;
  • Visibly cue the person that the area is a link;
  • Degrade gracefully to users without CSS or Javascript enabled; and finally
  • Integrate semantically into the document to make sense in the structure.

In this example we’re going to create a navigation menu for a web site. Our customer wants to have menu items that have a title and a small description. The designer wants the whole thing to be a link. Here’s how we pull it off.

Step One: Set up the menu

Typically while creating navigation menus using CSS, I tend to use unordered lists. For this example, it won’t work very well because there will be elements in each menu item that won’t work inside a li tag. To keep the document semantically correct, I want to use something like an h4 element for the title and paragraph tag for the description. Embedding these in a li element is technically valid HTML, but it’s a bad way to structure a document. I would even go so far as to say it’s similar to embedding structure inside nested tables. So we’re going to create a menu items out of div elements containing a headline and a paragraph element.

  <div class="menu_item">
  <h4><a href="index.html">Home</a></h4>
  <p>Go to the home page</p>
  </div>
  <div class="menu_item">
  <h4><a href="about.html">About</a></h4>
  <p>Read about how rad we are</p>
  </div>
  <div class="menu_item">
  <h4><a href="http://www.myfriendssite.com" rel="external">My Friend</a></h4>
  <p>My Friend's Site</p>
  </div>

That was simple, clean and valid HTML. Using h4 tags denotes importance, but not enough importance on the page to overrule your headlines. We have a short description in there with a paragraph tag. Notice we add a menu_item class to each div element. This is how we’ll work the magic later with Javascript.

Step Two: Set up the CSS

Now we’ll write some basic CSS to style the menu. Of course you’ll want to style it differently, so I’ll keep it super simple.

  div.menu_item {
    border: 1px solid #CCC;
    padding: 10px;
    width: 100px;
  }

Each menu item will be 180 pixels with a border and 10 pixels padding. Now let’s add a class for a hover state of the menu item. We’ll turn the background a slight gray and make the border darker. Then we’ll change the cursor to the pointer icon to make it appear to be a link.

  div.hover {
    background: #CCC;
    border: 1px solid #999;
    cursor: pointer;
  }

If Internet Explorer 6 played nice we’d add a :hover pseudo-class to the menu item in the CSS and be done. However, it doesn’t support CSS hover states on anything but links. Internet Explorer 7 in strict standards compliant mode does, but it’s currently a smaller subset of browser share. So we’ll need a little help from Javascript.

Step Three: Set up the Javascript

As with most of my Javascript snippets, you’ll need Prototype included in your page. For those just wanting to copy and paste the snippet and be done, I’ll throw it out now:

  function init_menu() {
    var items = document.getElementsByClassName('menu_item');
    items.each(function(item) {
      Event.observe(item,'mouseover',function() {
        Element.addClassName(this,'hover');
      }.bind(item));
      Event.observe(item,'mouseout',function() {
        Element.removeClassName(this,'hover');
      }.bind(item));
      Event.observe(item,'click',function() {
        var link = this.getElementsByTagName('a')[0];
        if (link.getAttribute('rel') == 'external') {
          window.open(link.href);
        } else {
          window.location = link.href;
        }
      }.bind(item));
    });
  }
  Event.observe(window,'load',init_menu);

For those who are still reading and want to know how it works, let’s go through it a few lines at a time.

How it works

First we get all the items in the document with the class name menu_item.

  var items = document.getElementsByClassName('menu_item');

Next we loop through each item found and apply event listeners to each one. Instead of the typical for (var i = 0; i < items.length; i++) pattern, we use Prototype’s each iterator, which cleans things up a lot in our code.

  items.each(function(item) {

The first thing we want to do to our menu item is apply a mouseover and mouseout state to it. We’ll add event listeners for the element to apply the hover CSS class to change the appearance. Since Prototype comes with a built in addClassName and removeClassName functionality, as well as event listeners using Event.observe, we don’t have to worry about supporting how it works across multiple browsers. Prototype handles that for us.

  Event.observe(item,'mouseover',function() {
    Element.addClassName(this,'hover');
  }.bind(item));
  Event.observe(item,'mouseout',function() {
      Element.removeClassName(this,'hover');
  }.bind(item));

Notice the bind call at the end of each even listener we set up. This allows us to reference the item as this inside the function block we pass into the event listener call. Otherwise it wouldn’t know what item you were referring to.

Now you might be thinking ‘how do you turn to the whole thing into a link when the link is only in the headline?’. Here’s how we do it: we parse the menu item and find the first link, then make the menu item listen for a click. When it’s clicked, it will open the link as though the real link inside the menu item had been clicked.

  Event.observe(item,'click',function() {
    var link = this.getElementsByTagName('a')[0];
    if (link.getAttribute('rel') == 'external') {
      window.open(link.href);
    } else {
      window.location = link.href;
    }
  }.bind(item));

It’s even set up to check for the rel="external" attribute of a link (covered in my previous post) and will open it in a new window if it’s present.

Finally we’ll set up an event listener to call the function after the page is loaded:

  Event.observe(window,'load',init_menu);

Stick this in an external Javascript file on your page or into the head of your document, and your menu items that can contain anything you want, and still appear as one large link. You can also apply it to more than than just menu items: use it on special callouts on your pages, such as download links, lists of previous blog posts, or product ads.

Users without Javascript enabled will still be able to view and click on links inside the menu items, they just won’t be as stylized as when Javascript is enabled. Search engines will also love your h4 headlines and description for each link, so your site could possibly rank for more relevant searches. What’s not to like?

I’ve uploaded a very basic example so you can see it in action. If you found this useful and applied it to your site, leave a comment and link to where you used it.

Map of online communities Spring 2007

Spring 2007 Community Map Way back in ‘95 I was born in Prodigy-land, which isn’t on this map, but I moved shortly to the coast of the Noob sea in AOL. I spent my youth to the East in the BBS isles, which have since been swallowed up by the Anthromorphic Dragons. At that time the rest of the world was undiscovered territory filled with tales of pirates and anarchy cookbook text files. When I grew up I migrated south and spent time between the IRC Isles and Usenet.

Superchomp gonna eat you!

No newlines are safe!!

  class String
    def superchomp
      self.strip.gsub(/^(n|r|rn)+|(n|r|rn)+$/,'')
    end
  end

Please only use it for good and not evil.