Coding with Jesse

Accessibility Is About Minimizing Requirements

September 30th, 2007

What are the minimum requirements for using the web?

  • an Internet connection
  • a web browser

What are the minimum requirements for using your web site? Well, the answer could include any of the following:

  • a high-speed Internet connection
  • a keyboard
  • a mouse (and the ability to use a mouse)
  • a large computer screen (eg. 1024x768+)
  • specific web browser versions (eg. IE 7, FF 2+)
  • specific browser plugins and version (eg. Flash 7 or VRML)
  • JavaScript
  • a PDF viewer
  • near perfect vision
  • lack of colour blindness
  • knowledge of a language (English) or jargon (web development)
  • potentially many more...

How many requirements does your site make? How many are really necessary and how many can you eliminate?

Being accessible means minimizing requirements. The less requirements you have, the more freedom people have to use your site, the more accessible it is to the world.

The more requirements you make, the more you're requiring people to have specific devices, software and even physical abilities that may not be possible. As a result, the site becomes inaccessible to some.

Of course, some requirements are necessary. Can you imagine a web site translated into every language? And what would this blog be without assuming a basic knowledge of HTML, JavaScript and CSS?

But how many are just trivial requirements, made to save a bit of programming or decision making? And how many are simply unreasonable given the wide range of physical and technical limitations people face in the world?

One thing is for sure: plain HTML makes the fewest requirements. Start with that and add other technologies carefully and unobtrusively.

CSS Sprite Generator

September 30th, 2007

Finally, there is an automated CSS Sprite Generator (via)! Just upload a zip of graphics and it will spit out a single image and a block of CSS you can use.

What are CSS Sprites? If you use a ton of CSS backgrounds for things like icons, buttons and other non-repeating graphics, then you can combine them into a single graphic and use background-position with width and height to show a slice of the larger graphic. This can make a site load faster since there are less files to download.

This is generally a pain to do by hand (not only combining the graphics, but calculating and remembering pixel positions), but with a tool like this it should be a cinch!

Getting an Image's onload to Fire

September 28th, 2007

Are you attaching an onload function to an image but finding it doesn't always get called?

The problem is almost always this: you need to set the onload before you set the src. The reason is obvious when you think about it: if the image is in the cache, the image will be loaded immediately after setting the src, even before the onload is set.

Adding fuel to the fire, Firefox and Safari will let you set an onload immediately after (it seems they don't call the onload until the block of JavaScript finishes). This doesn't happen in Internet Explorer or Opera.

Long story short:

// evil:
var image = new Image();
image.src = 'image.jpg';
image.onload = function() {
    // sometimes called
    alert('image loaded');
};

// good:
var image = new Image();
image.onload = function() {
    // always called
    alert('image loaded');
};
image.src = 'image.jpg';

No matter how many times I come across this bug and find the solution, I end up making the same mistake a few weeks later. I'm hoping that blogging about it will get this stuck in my long-term memory.

Using Hash for JavaScript Debugging

September 26th, 2007

No, I don't recommend smoking hash before doing your JavaScript debugging :) But I did figure out a technique which you can use to switch a page in and out of debugging mode.

What happens if you need to debug a site that's getting traffic, and you don't want everyone getting your alert() messages or whatever else you need to debug?

Well why not check location.hash and look for a special keyword:

function debug_mode() {
    return location.hash == '#debug';
}

if (debug_mode()) {
    alert('We are in debug mode!');
}

Now you can just add #debug to the URL (and hit enter) to turn on debug mode, or just drop the #debug to turn it off. You can even have more than one special "mode" and use different hash values to switch between these modes.

Detect Internet Explorer 6 in JavaScript

September 21st, 2007

Update: As some of the comments mention, the technique below doesn't work anymore. It's best to use object detection to accomplish what you need, or use conditional comments. But if you need to detect IE6, this should work: /MSIE 6/i.test(navigator.userAgent)

Sometimes you just have to sniff for Internet Explorer 6 (and under) in JavaScript. Using conditional comments is a decent solution, but I don't want them scattered all over my code.

With a bit of help from Dean Edwards, I worked out the following:


var IE6 = false /*@cc_on || @_jscript_version < 5.7 @*/;

With just a single conditional comment, you can have a JavaScript variable that you can reuse throughout your code.

(IE6 will be true in Internet Explorer 6 and under, but does anyone really care about IE5 anymore? Thought not.)

You could use this technique to sniff for other things:


// exactly Internet Explorer 7
var IE7 = false /*@cc_on || @_jscript_version == 5.7 @*/;

// at least Internet Explorer 7
var gteIE7 = false /*@cc_on || @_jscript_version >= 5.7 @*/;


// any Internet Explorer (thanks to Dean)
var isMSIE = /*@cc_on!@*/false;

Note: browser sniffing is evil but sometimes painfully necessary.

jQuery 1.2 Notes

September 11st, 2007

Great news: jQuery 1.2 is out, and the heavily-awaited jQuery UI (an "official" replacement to Interface) will be out on Sunday.

Be sure to have a read of the jQuery 1.2 release notes, but here are a few highlights that I can't wait to use:

  • Partial .load()

    If you want to load a whole web page with Ajax, but only want to cut out a portion of the page and stick it in to an element on your page, you can now do this:

    $('#stats').load('same_page.php #stats');
    

    This will make it really easy to refresh an element on the page without needing to change the server-side logic.

  • New Traversing Features

    Traversing and selecting remain the most powerful features in jQuery, and it'll be great to be able to use .andSelf() to include the original set when traversing, and .prevAll()/.nextAll() to select all the siblings to one side or the other.

  • New Effect Features

    There are a ton of new Effects features, but my favourite is probably .stop(), allowing us to finally stop animations. Together with the new :animated selector, it's trivial to stop all ongoing animations at once:

    $(':animated').stop();
    

    Some of the other Effects features have a lot of potential, like being able to use percents or animating by a relative amount (eg. add 100px).

    Extremely powerful is the new ability to write extensible animations. I assume they did this to ease in the development of jQuery UI, but this allows all of us to harness the power of jQuery animations to do anything we want! Okay I'm starting to drool...

Oh, one more thing. If you're used to creating elements in jQuery like this:

var link = $('<a>');

then you need to stop using invalid HTML and either make it XHTML compliant or add a closing tag, otherwise it will break in Internet Explorer. This is true since jQuery version 1.1.4, and I've had to make a lot of changes in my code as a result.

Now any of the following is okay:

// okay, XHTML-style
var xhtmllink = $('<a/>');

// also okay, valid HTML style
var htmllink = $('<a></a>');

Avoiding web page zoom in the iPhone and iPod Touch

September 7th, 2007

I've been doing a bit of experimentation with web pages in the iPhone, and I've realised the first major problem is trying to prevent the iPhone from zooming way out on a web page, making it rather difficult to work with and more difficult to read.

One would assume that a 100%-width layout would be good enough for the iPhone's Safari to stop setting the browser width to 964px. But alas, it's not.

I had a look at probably the best iPhone app out there right now, Joe Hewitt's Facebook for the iPhone. Joe was awesome enough to release iUI, a collection of CSS, JavaScript and images for making user interfaces that match the look and feel of the iPhone.

I spent some time dissecting his examples, and eventually realised it wasn't the CSS nor the JavaScript which was able to stop the iPhone Safari from resizing. It was just a <meta> tag in the <head>:

<meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>

It turns out this was all well documented on Apple's site, iPhone for Web Developers. There are lots of other techniques discussed like how to specify stylesheets and integrate with the built-in Google Maps application.

I hope that other device manufacturers implement things like the <meta name="viewport"> tag and the only-for-certain-widths stylesheets. The iPhone may not end up in everyone's pocket, but we will need to make web sites and applications that work across an ever-wider range of devices.