Centre div in window no matter what – Version 2

In a previous post I showed you how to center a div on screen regardless of if it was inside an iframe or not. This is the second version, which should work regardless of if the div is in the top level window, an iframe, or a regular frame.

	Name: center
	Description: Center a div on page, no matter what!
	Author: AK (www.zeroedandnoughted.com)
	Date: 22nd April 2009
	Version: 0.2
	Dependencies: jQuery
	(function($) {
	    $.fn.center = function() {
	        return this.each(function() {
				var $this = $(this);
				var frameXOffset = 0, frameYOffset = 0, windowHeight = 0, windowWidth = 0;
				//Are we in a frame?
				if (top.document != window.document) {
					var frm = $('iframe',top.document.body);
					if (frm.length == 0) {
						//regular frame
						frm =  $('frame',top.document.body);
					var i=frm.length;
					while (i--) {
						if (frm[i].contentDocument) {
							doc = frm[i].contentDocument;
						} else {
							doc = frm[i].contentWindow.document;
						if (doc === document) {
							//located our frame!
							frameXOffset = $(frm[i]).offset().left;
							frameYOffset = $(frm[i]).offset().top;
					if (jQuery.browser.msie) {
						windowWidth = top.window.document.documentElement.clientWidth;
						windowHeight = top.window.document.documentElement.clientHeight;
					} else {
						windowWidth = top.window.innerWidth;
						windowHeight = top.window.innerHeight;
				} else {
					//we are not in a frame
					if (jQuery.browser.msie) {
						windowWidth = window.document.documentElement.clientWidth;
						windowHeight = window.document.documentElement.clientHeight;
					} else {
						windowWidth = window.innerWidth;
						windowHeight = window.innerHeight;
				var elHeight = $this.height();
				var newTop = ((windowHeight/2) - (elHeight/2)) - frameYOffset + $(parent.document.documentElement).scrollTop();
				if ((newTop + elHeight) > $(document).height()) {
					newTop = $(document).height() - elHeight;
				$this.css ({
					left: ((windowWidth/2) - ($this.width()/2)) - frameXOffset + $(parent.document.documentElement).scrollLeft(),
					top: newTop

Checking for Duplicates in a JavaScript Array

JavaScript has an in operator, that allows us to look through an object to see if we can find a property. If we create an object containing particular items in an array, we can then look through those items to see if we find a match.

Using prototypes, we can easily create a new method that will apply to all arrays. Let’s look at this in pieces.

The first thing we want to do is attach a method to the array prototype.

Array.prototype.containsDuplicates = function() {};

We can now do something like:

var dupesFound = [1,2,3].containsDuplicates();

…although this will won’t yet return anything, of course.

The next thing we’ll want to do, is loop through the contents of our array. For each item we will need to create an array with every item except our current one to check against (otherwise we will match against our current item, and always find a match).

In my previous post on iterating through arrays we already know the fastest way to iterate through an array (assuming we don’t mind doing it in reverse) so we’ll do that, and for each iteration create a new array containing all but the current item using the slice() and concat() methods.

var i=this.length;
var a;
while (i--) {
	a = this.slice(0,i).concat(this.slice(i+1,this.length));

Next, we’ll create an object and loop through our new array, creating an empty property of the object for each item in the array.

o = {};
j = a.length;
while (j--) {
	o[a[j]] = '';

Finally, we can now check this object for our current item, and return true if we found a match.

if (this[i] in o) {
	return true;

So, putting it all together (remembering to return false if we don’t find a match:

Array.prototype.containsDuplicates = function() {
	var i=this.length;
	var a, o, j;
	while (i--) {
		a = this.slice(0,i).concat(this.slice(i+1,this.length));
                o = {};
                j = a.length;
                while (j--) {
                    o[a[j]] = '';
		if (this[i] in o) {
			return true;
	return false;

I generally don’t advocate modifying the base prototypes in JavaScript – it can cause all sorts of problems later on, so here’s the same methodology as a function.

var containsDuplicates = function(a) {
	var i=a.length;
	var a2, o, j;
	while (i--) {
		a2 = a.slice(0,i).concat(a.slice(i+1,a.length));
                o = {};
                j = a2.length;
                while (j--) {
                    o[a2[j]] = '';
		if (a[i] in o) {
			return true;
	return false;

I hope this helps someone. Feel free to suggest ways to make this more efficient.

Building Accessible Websites – Part 1: Visual Impairment

The statistics from the RNIB show that 5.9 children in 10,000 have some kind of visual impairment. There are around 80,000 people in the UK that are registered as blind or partially sighted. That is a significant number of people, and if your website can expect a reasonable amount of traffic it is a number you should be paying attention to. Quite apart from that, it is a legal requirement that we do not discriminate against people in any way. If your data is public, everyone should have access to it.

The Disability Discrimination Act makes it unlawful for a service provider to discriminate against a disabled person by refusing to provide any service which it provides to members of the public. From webcredible.

Fortunately, building websites in a semantic and SEO-friendly manner has the side effect of making a site that is likely to be screen-reader friendly. That is – if you are building websites well, the issues this kind of impairment presents are less problematic than you might expect.

Screen readers

Users who are considerably visually impaired will employ some kind of screen reader to help them use their computer. For the web, this is a tool the gives the user methods to hear the text on a site, and quickly jump to sections of a page. A lot of screen readers are available, and they all work in slightly different ways (like web browsers or mobile web browsers). They are very expensive to upgrade, and upgrades are available often, and because of this it is my experience that many users do not often upgrade screen readers. Many screen readers do not allow JavaScript, and those that do typically make it easy to disable. I usually make the assumption that a screen reader user will have JavaScript disabled, although where easy I do anything I can to make JavaScript as screen reader friendly as possible. A lot of JavaScript enhancements for a user with normal eyesight will not be of much use to a screen reader user anyway. Having watched experienced users of screen readers, I can say that they are able to make use of an accessible website very quickly indeed, and listen to the text being read out at upwards of 180 words per minute! At that speed, to me it just sounds like gibberish. Apple’s VoiceOver can apparently speak intelligibly at over 750 words per minute.

Using a Firefox extension such as Fangs will let you emulate a screen reader’s behaviour, to a degree. Use this to help you get the hang of building a page in a linear fashion – remembering you need to describe things before they happen, not after.

Semantic HTML

The first rule is to apply POSH to all of your content. This is an important rule anyway, for the semantic web. The importance of this is beyond the scope of this article, and I will revisit it in a dedicated blog entry in the future. Most screen readers are able to quickly offer the user an audible representation of an outline of the document, for example, all of the level two headings on a page, or all of the forms on a page. Using POSH has many other benefits including SEO, consistent and higher quality code, validating code and future-proofing.

Skip links

Using in-page anchors to allow the user to jump to sections of the page is vital. At the very least they allow the user to jump straight to the navigation and the main content. If these anchors do not fit your design, use CSS to give these position: absolute; and left:-9999px;. Although we cannot guarantee this in the future, current screen readers typically will not read out content that is display: none; or visibility: hidden; (assuming, correctly that it is not visible) but they will read out content that is positioned off-screen. To make these more useful you can use a CSS :focus selector to bring these links back into view when the user uses the keyboard to tab to them, benefiting all other users at the same time. Use the same trick for “Back to Top” links and your user now has a way to leap around your page, without having to listen to all the content.

Consider links as holistic entities

Users of some screen readers have the ability to immediately list (audibly) all of the links on a page. These are (usually) listed one at a time, as the text (or alt text) inside the anchor tags. This means if your text says something like “click here to go to website A”, a screen read user will hear just the word “here”. If you have this all over the page they will hear just “here”, “here”, “here” and so on, which is not useful – in fact, very frustrating. Instead, try to make the links an entity in their own right, something more like “go to website A“. Where this is difficult, for example at the end of an excerpt from an article you might have a link that says “more…” that takes you to a page that details the entire article. You could actually surround this in other text so the text says “more about this article on wombats…” and ” about this article on wombats” is in a span which employs the same trick as above to take it out of the flow and position it off-screen.

AJAX/DOM hooks

When you use JavaScript to modify the contents of the page (perhaps as a result of an AJAX call), the screen reader may be reading at a position below that point. The screen reader may not notice that the contents of the page have been changed, meaning the user will have to start reading the page again at the top to find the change. There are methods you can employ to try to give a screen reader hints that the page has changed, and to offer the user a chance to leap to that point. The full extent of this is beyong the scope of this article, but ajaxian provide a great guide to accessible AJAX best practices.

Frames/iFrames == Bad

Quite aside from the plethora of other reasons you should be avoiding frames, they make the life of a screen reader very difficult. Which frame should we currently be reading? When do we jump focus to another? How do we present audibly that these are different entities, if in fact they are? Frames were designed to help solve a problem, but they ultimately just create more problems says www.webaccessstrategies.com and I concur.


Most operating systems give the user the ability to zoom in on any part of their screen. This works operating system wide, not just for web browsers. Applications can be acquired to achieve the same end, and this is really how accessibility should be handled – in a consistent, system-wide fashion. Since all these are doing is helping the user focus on a section of the page, the only caveat here is to remember to try to stop our paragraphs or blocks of text from being too wide (within reason) so the user does not have to endlessly jump back and forth to read sentences. Keeping our text in reasonable width blocks like this will also help some people with learning disabilities (to be covered in a future post) to read our content.


CAPTCHAs help us try to ensure our website is being accessed by a real person. It is vital to accept these are not fool-proof. A computer program can be formulated to read any text that we can, especially if the operational parameters of a particular CAPTCHA can be figured out. Even if you are really clever (recently I saw a CAPTCHA showing nine women, one of which was clearly more attractive than the others) techniques can be used to get around this. One pornographic site presented users with a CAPTCHA from Yahoo! when they were signing up, so that without knowing, they were actually helping the site build fake Yahoo! accounts in the background. (CNET story.)

Whilst they cannot be relied upon, CAPTCHAs just make it that bit more difficult for someone trying to abuse your site. As we know, in essence, they present you with an image and ask you questions about it. It is possible to also present this data audibly, but by now this is a huge undertaking to do well, and one more thing you don’t really need to be developing and supporting. To address these issues, I cannot recommend the reCAPTCHA project enough. Not only are you using an API to implement a mature and working CAPTCHA with audio and skinning support, your users are also helping to digitise books! Read more at the reCAPTCHA site for details.

Scalable text

The text on your site should all be in a relative unit be in based on percentages or “ems”. According to Wikipedia An em is a unit of measurement in the field of typography, equal to the point size of the current font.. You should be able, as a rule of thumb (my thumb, in this case) to resize your font up or down by two sizes. Resizing up has an obvious value – it makes the text easier to read. I have even done this. Running a Mac Mini on a big screen TV at HD resolution actually makes text impossible to read. Until we get resolution independence, jumping the font size up a couple of sizes provides a quick fix. You also need to be able to turn the font-size down, which may surprise some people but it’s important that text remains readable even when using the “Smallest” setting. This is important for users with tunnel vision who may wish to fit as much text in their line of sight as possible (from the RNIB Web Access Center).

The most recent browsers are now starting to scale up the entire page when the user chooses to increase font-size (though they can sometimes choose to isolate this effect to text only) resulting in pixelly graphics, but maintaining layout. For maximum compatibility, liquid layouts will cope better with text-only font size changes, and can help maximise the use of a browser’s screen estate at different resolutions. I recommend not going over the top with this. Supporting resolutions of 800 x 600 up to 1440 x 900 is a reasonable thing to do, but although supporting an HD resolution might be technically impressive, an entire paragraph on a single line is not easy to read, nor does it normally look attractive.

Colour blindness

The BBC has a tool (internally referred to as “Barlesque”) which allows the user to set various display options according to their impairment. Several colour schemes are available, which are appropriate for different levels and types of colour blindness. These sittings change a stylesheet which is applied to the site, for different colour schemes which users will find easier to read. For those of us who cannot afford the luxury of implementing this kind of functionality, our goal must be to expect a reasonable lever of contrast between text and the background. Snooks have a tool to tell you the brightness and colour difference between two colours, and whether or not the contrast ratio is acceptable. I would suggest their acceptable levels are a bit unrealistic, and you should be trying to aim for 125 or more brightness difference, and 400 or more colour difference. Access Keys also provide a tool to scan an entire page and give you a report on the contrast of text on that page.

Images and alt text

Images should only have alt text where the image has value as content. Alt text is “alternate” text. This means it is an alternative to the image, for users who have chosen not to download images or are not able to view them. If a link is an image that has the text “Order Now” on it, it needs an alt attribute that says “Order Now”. If it is a swirly blue pattern, or someone looking happy using a computer, or any other kind of image that does not provide value to the page other than aesthetically, it does not need alt text. It does need to have an alt attribute, to validate, but that attribute can be empty.

Where you have extra information to include such as copyright data for an image, or detailed descriptions of the location the title attribute is more appropriate. Where this information is very lengthy, the longdesc attribute can contain the address of a page with more details.

Pet hate: it is not an alt tag! It is alt text, or (more accurately) an alt attribute.


Try your absolute hardest to keep the layout and style of your pages consistent. If the user can always expect to find the content here and the navigation here, they can learn to navigate your site more efficiently very quickly. If you are employing skip links too, they will rapidly learn where these are and where they lead.

Some extra resources

In the next part of this series, we will look at hearing impairments.

Making web service APIs that play nicely

We are part of the way through writing stories for the next Silver Squid project and I thought I would share some of these to do with the basic requests and responses of our web service APIs.

Choosing Data Types

Something that I feel is important, is to allow the user of your APIs to send and receive data in the format of their choice. They may be trying to integrate your system with one that only speaks one language, or they might be better versed in some than others.

With that in mind, our latest project allows the user to set whether they are sending data as a normal form submission (necessary in this instance, to allow the user to send files), as XML or as JSON. We allow these to be set in HTTP headers, so that they are set before the system examines the sent data at all. The story is as follows:

As an API user
I want to be able to send HTTP headers defining my request and response data types
so that I can better integrate the API with my system

Acceptance criteria:

  • M: A requestDataType header can be sent – the values can be: form, xml or json. This should dictate the expected data and default to form: if not provided.
  • S: If requestDataType is set to a different value the error ERR_UNSUPPORTED_REQUESTDATATYPE should be thrown.
  • M: A responseDataType header can be sent – the values can be: xml or json. This should dictate the response data type, and default to xml if not provided.
  • S: If responseDataType is set to a different value the error ERR_UNSUPPORTED_RESPONSEDATATYPE should be thrown (in XML).

I have begun to employ the MoSCoW Method for acceptance criteria priorities. According to Wikipedia – these are defined as:

MUST have this.
SHOULD have this if at all possible.
COULD have this if it does not affect anything else.
WON’T have this time but WOULD like in the future.

It is very helpful to have a convention to follow for things like this, and this method seems as good as any other.

Consistent Errors

You’ll see that I have defined the errors that will be thrown, and specifically stated that when the Response Data Type cannot be inferred, to use XML.

I try to always be very specific about the error that will be thrown, and to throw those errors in a consistent manner. It feels natural to me to throw HTTP errors when our API fails, and for a while I tried to always throw the appropriate HTTP error code. I gave up on this, because there just is not always an appropriate error code. Now we always throw a 500 error, and provide a string describing the specific error, in the format requested by the user. The story in this project that defines this is:

As an API user
I want errors to be thrown in a consistent fashion
so that my system can detect these and respond appropriately

Acceptance Criteria:

  • M: When an error is thrown, the system should return an HTTP error code of 500.
  • M: When an error is thrown and responseDataType is set to xml (or missed out and thus defaulted), the error should take the following format:
    <?xml version="1.0" encoding="UTF-8"?>
  • M: When an error is thrown and responseDataType is set to json, the error should take the following format:
  • S: All error codes should begin with ERR_.
  • S: A default error of ERR_UNSPECIFIED_ERROR should be thrown when we can not further isolate the error.

This should make it easy to predict the error formats, and also make them easier to write. Knowing that all errors will begin with “ERR_” allows the user of our API to easily handle for all errors, and add more specific handlers when/if necessary, although checking for an error property or node is enough to detect that an error was thrown.

I hope this has been useful. How do you deal with errors and data types in your APIs?

How to do Agile Properly – Part 2: Design

Part 1 of this series

Designers naturally fight against the Agile process, and it is hard to blame them. The typical process defines that the designer provide little pieces of a design at a time. This doesn’t make sense – a design is a holistic piece of creativity in its own right. Imagine if you were asked to draw a house, but piece-by-piece. First, draw the chimney. Now a window box. Now a hill in the background. Now the front door. It would drive you crazy, and of course, whenever you sketched the next bit in, you would have to change the previous ones to keep the composition sensible.

In practise, trying to shoe-horn the designers into this process ends up (in places I have worked, at least) with the developers being halfway through implementing the design on the stories for the current iteration, and the designers being halfway through changing everything for the next one. I would catch a glimpse of the designer’s screen, and see that everything I had done so far was already out-of-date. This problem would progressively worsen with every iteration. It was disheartening, and inefficient.

This isn’t the designer’s fault. They are not used to the same restrictive processes that developers are, and they shouldn’t be. They need more room to be creative.

Colouring It In

Before any designs can be built, we need to have a good idea of what it is we are building. Brainstorming ideas and mad designs is all well and good – but this should certainly take place before any development begins. That said, whilst the stories are being written, it’s a great idea to be throwing together a few off-the-wall designs, to be treated as prototypes. This gives the designers a chance to work without restriction and really express themselves creatively. Some great ideas can come out of this process.

Once the stories are written, we can move on to wireframes. This is where our design starts to get some structure, and this what our developers will be able to initially start working with. There are lots of tools for creating wireframes – OmniGraffle, Visio, and so on. My tool of choice would definitely have to be Balsamiq Mockups.

It can be very easy to start treating a wireframe as a design. I’ve been in several meetings where it’s been suggested the font is too small, or the colours in the wireframes are wrong and so on. The point of a wireframe is to map out what elements we can expect to have in a design, relationships between pages, and their basic interation and positioning. The wonderful thing about Balsamiq Mockups is the result looks like a sketch. There is no way you could mistake it for a design, and this keeps conversations focussed on the important points. Here is an example I made in less than two minutes!

Balsamiq Mockups

Balsamiq Mockups is available as a standalone app, or as plug-ins to Jira and Confluence (my management tools of choice). It stores data in XML format, and the web-enabled versions of the software have very little disadvantages over the desktop app. I recently chatted with Giacomo ‘Peldi’ Guilizzoni (the company’s founder) over Skype, and he was a lovely and helpful guy. The desktop version is only $79 per user. The plug-ins include licenses for up to 3 desktop versions, and you can get a refund of the difference if you bought the desktop version first!

We’re Good To Go

So, now we have our stories, and our wireframes. It is at this point development would begin. We will concentrate on the design track first. Since we have valid wireframes, and we know what elements to expect on our page, our developers can get on with functionality, and good, clean POSH. The design does not have to exist at this point. I have found, at Silver Squid that developing without design first let’s the developer get the cleanest code, and the designer work without restriction.

Our first story might be:

As a Designer I want to create a base design so that I have a template to build further designs upon

For this the designer should get an idea of the design language of the site, the colour schemes, the typography, and so on. Of course, this is Agile and as such it can all change, but having somewhere to start is A Good Thing. It should be based upon the prototypes they built in the planning stage, which were hopefully well received!

Following that, stories could be something like:

As a Developer I want a design for navigation to exist so that I can apply it to the HTML to make the site more attractive

This means that the designer focusses on the navigation. The wireframes should have included basic expected behaviour – whether the navigation is dropdown, or static, etc. The acceptance criteria will list the expected states of the navigation, to ensure all scenarios are covered. For example:

  • Navigation Item
  • Active Navigation Item
  • Hovered Navigation Item
  • Navigation Item with Subnavigation (contracted)
  • Navigation Item with Subnavigation (expanded)
  • Subnavigation Item
  • Active Subnavigation Item
  • Hovered Subnavigation Item

There are a lot of potential states in a even slightly complex web app. Making sure these are all covered in the acceptance criteria leaves little room for error later. We should also allow in each story for amendments to the rest of the design to keep everything feeling coherent.

Don’t Forget Interaction & Animation

The latest and greatest web apps have sliding menus, fading modal dialogue boxes, pulsing buttons etc. Any dynamic movement like this will not come through in your static Photoshop files. It is important that these are decided by a qualified designer or UX guy, and that he works with the front-end developers to ensure it works as he expects it to. As much as possible should be noted along-side marked up designs. Often these touches get forgotten and the front-enders make it up themselves, which can be a huge mess of sliding, throbbing, fading, scaling madness.

As I’ve said before, these are practises that work for me! Everyone is different. How do you implement design in your Agile process?

In part 3, we will start breaking down the development process into its component parts, and show how the team works together to get things done.

Using previously highlighted text in TextMate snippets

In a previous (and very verbose) post on TextMate snippets, I showed a snippet to easily and simply use a tab trigger to insert a try... catch statement. If you missed it feel free to catch up here. The idea was that you type in try, press tab and TextMate spits out:

try {

} catch(e) {


Now, the cursor is automatically positioned inside the try block, and the next time you press tab it moves to the catch block. Pressing tab again moves you outside the block. This is great, but not hugely useful in the real world. What would be more likely than writing an empty try... catch statement up-front would be to write some code, and choose to surround it in the try block. I promised to tell you how to do that, and it is much simpler than I thought.

The answer is the TextMate variable $TM_SELECTED_TEXT. It does exactly what it says it does, but you can’t use a tab trigger to achieve our goal here. Highlight some text, and start typing and of course, the text is overwritten. In this instance, a tab trigger will not do. You need to use a "Key Equivalent" (or hotkey or shortcut key to the rest of us). In my instance, I have more than enough of those to remember already, thankyouverymuch, and so I highlight the text and do one of the following:

  • Click the Bundle menu item at the top of the screen and drill down to my snippet
  • Press Ctrl+Escape and drill down to my snippet
  • Or, my favourite, press Ctrl+Command+T to bring up a list of all the snippets, type "try" to filter the list, and press return

There is nothing to stop you just typing try and pressing return either.

Here is the final snippet:

try ... catch
Tab trigger:
try {
} catch(e) {

try... catch TextMate Bundle Editor Example

Note that there should be a trailing extra carriage return, to ensure the final tab takes us out on to the line following the block.

Six Ways to Iterate Through an Array (or Chrome’s V8 is a Monster)

There are actually all kinds of ways to iterate through an array in JavaScript. Here, I will concentrate on six of them, describe their advantages, and do performance testing to actually prove which of them is the faster.

Loop 1 – the native for loop

for (var i=0; i < arrTestData.length; i++) {
	/* do stuff */

We’ve all seen this a million times. It is the easiest to read, and the most common. It is also the least efficient.

Loop 2 – the native for loop improved

for (var i=0,j=arrTestData.length; i<j; i++) {
	/* do stuff */

The improvement here, is that a second variable j is employed, to stop us having to query the length property of the array with every iteration. Getting the length can be a costly process and it makes more sense to just do this once. Where it is important that iterate incrementally, and in ascending order (i.e. 0,1,2,3,4,5) this is the fastest method.

Loop 3 – the native for loop in reverse

for (var i = arrTestData.length - 1; i >= 0; i--){
	/* do stuff */

The main advantage of this method is that only one variable is employed. It is slightly faster than the other for loops, but goes in descending order (i.e. 5,4,3,2,1,0) which may make it inappropriate for your needs.

Loop 4 – the native while loop

var i = 0;
while (i < arrTestData.length) {
	/* do stuff */

This is essentially the same as Loop 1. We are still querying the length of the array with every iteration.

Loop 5 – the native while loop in reverse

var i = arrTestData.length - 1;
while (i > 0) {
	/* do stuff */

This is essentially the same as Loop 2. We are storing the length of the array, to avoid querying with every iteration.

Loop 6 – the native while loop in reverse improved

var i=arrTestData.length;
while (i--) {
	/* do stuff */

This is the tidiest code, and the fastest. Since a zero integeric value is falsy, our condition is as simple as it could be, and only one variable is employed. I give credit to Richard Hubbard (get a blog already, Richard!) for showing me this.

Below, are the results of my testing.

OS Browser Test Result 1 Result 2 Result 3 Average
OSX 10.5.6 Firefox 3.0.5 Loop 1 46ms 47ms 46ms 46ms
Loop 2 31ms 32ms 31ms 31ms
Loop 3 34ms 33ms 33ms 33ms
Loop 4 46ms 45ms 46ms 45ms
Loop 5 32ms 32ms 32ms 32ms
Loop 6 29ms 29ms 29ms 29ms
OSX 10.5.6 Safari 3.2.1 Loop 1 44ms 45ms 43ms 44ms
Loop 2 33ms 32ms 34ms 33ms
Loop 3 31ms 33ms 31ms 31ms
Loop 4 45ms 45ms 45ms 45ms
Loop 5 33ms 33ms 33ms 33ms
Loop 6 29ms 29ms 29ms 29ms
OSX 10.5.6 Camino 1.6.4 Loop 1 106ms 93ms 91ms 96ms
Loop 2 67ms 64ms 61ms 64ms
Loop 3 61ms 64ms 61ms 62ms
Loop 4 91ms 90ms 90ms 90ms
Loop 5 61ms 64ms 67ms 64ms
Loop 6 60ms 60ms 60ms 60ms
OSX 10.5.6 Opera 9.61 Loop 1 34ms 32ms 31ms 32ms
Loop 2 23ms 24ms 29ms 25ms
Loop 3 24ms 23ms 23ms 23ms
Loop 4 32ms 31ms 32ms 31ms
Loop 5 22ms 26ms 23ms 23ms
Loop 6 26ms 25ms 25ms 25ms
Windows XP SP2 Chrome Loop 1 2ms 3ms 2ms 2ms
Loop 2 2ms 2ms 2ms 2ms
Loop 3 2ms 2ms 2ms 2ms
Loop 4 3ms 3ms 3ms 3ms
Loop 5 2ms 2ms 2ms 2ms
Loop 6 2ms 2ms 2ms 2ms
Windows XP SP2 IE 7.0.5730.13 Loop 1 171ms 172ms 172ms 171ms
Loop 2 125ms 125ms 125ms 125ms
Loop 3 125ms 125ms 125ms 125ms
Loop 4 1172*ms 172ms 172ms 172ms
Loop 5 125ms 125ms 141ms 130ms
Loop 6 125ms 125ms 125ms 125ms
Windows XP SP2 FF 3.0.5 Loop 1 37ms 37ms 37ms 37ms
Loop 2 26ms 26ms 26ms 26ms
Loop 3 25ms 26ms 25ms 25ms
Loop 4 37ms 36ms 37ms 36ms
Loop 5 25ms 25ms 25ms 25ms
Loop 6 27ms 26ms 27ms 26ms
Windows XP SP2 Safari 3.2.1 Loop 1 53ms 52ms 53ms 52ms
Loop 2 40ms 39ms 40ms 39ms
Loop 3 39ms 40ms 40ms 39ms
Loop 4 55ms 55ms 54ms 54ms
Loop 5 41ms 41ms 40ms 40ms
Loop 6 37ms 37ms 37ms 37ms
Windows XP SP2 IE 6 (multiple IEs) Loop 1 156ms 172ms 156ms 161ms
Loop 2 109ms 125ms 109ms 114ms
Loop 3 110ms 125ms 125ms 120ms
Loop 4 156ms 1313*ms 156ms 541ms
Loop 5 125ms 109ms 125ms 119ms
Loop 6 125ms 110ms 125ms 120ms
Windows XP SP2 Opera 9.63 Loop 1 16ms 31ms 16ms 21ms
Loop 2 16ms 15ms 16ms 15ms
Loop 3 15ms 16ms 16ms 15ms
Loop 4 31ms 16ms 31ms 26ms
Loop 5 15ms 16ms 16ms 15ms
Loop 6 0ms 15ms 16ms 10ms

I did every test three times, and took the average as the result. Internet Explorer 6 and 7 both presented a confirm dialogue box, asking if I wanted to keep running the script, which paused execution of the code. This resulted in two vastly bloated results, which I have generously ignored. It didn’t help – IE is the obvious loser here in every instance, surprisingly showing very little improvement between IE6 and IE7.

Copying the data was a pain – although in OSX I could copy and paste from pretty much any source, including alert dialogue boxes. In Windows only Firefox would let me do this.

A shock in all of this, was just how fast Chrome performed, clocking in at 100,000 iterations per millisecond! I actually wrote different versions of the code just for Chrome, just to ensure it was actually doing something. That V8 engine they have in there is amazing.

The point of this, though, is not to compare browser speed. Of course, we can’t compare between OSX and Windows XP in this instance, the hardware was different. Also, this is just a very specific and small set of tests and cannot be considered a fair test of browser speed. Really, what we wanted to achieve was to see which method of iterating through an array is the most efficient.

To that end, here is a final table, showing the average result across browsers for each loop.

Test Average Result (ms)
Loop 1 73.6
Loop 2 52.6
Loop 3 52.7
Loop 4 73.1
Loop 5 53.6
Loop 6 51.4

The obvious conclusion is that although Loop 6 is the fastest, there is not that much in it – whereas Loop 1 and Loop 4 are dramatically slower than the others, demonstrating just how expensive the querying of the length property is.