Christian Heilmann

You are currently browsing the archives for the usability category.

Archive for the ‘usability’ Category

Interfaces that have to die – the onchange select box

Thursday, July 10th, 2008

It is scary how some obviously bad practices refuse to go away and developers jump through hoops to defend them and make them work rather than using simpler alternatives.

My pet peeve is the “chess rules” select box (you touched it, it needs to move):

This is the most evil permutation of this interface idea. A lesser evil version is part of a large form that will change the rest of the form or – if we venture back into more evil lairs – submits it to reflect these changes.

The arguments for this interface are not many:

  • It saves the user one step of pressing a submit button
  • The action is immediate

(Ok, these are actually the same argument, comment if you know some.)

The drawbacks of the solution are immense:

  • People that use a keyboard will submit the form or leave the page without having selected the right option.
  • People that are dependent on using a keyboard for web access will possibly know that you can press the Alt+Arrow Down keys simultaneously to expand the whole dropdown before selecting with arrow up and down and enter.
  • Most people won’t know this though and a lot of people use keyboards and tabbing from field to field to fill out forms.
  • Forms are a terrible annoyance of our times – nobody likes filling them in. Most of the time we won’t keep our eyes on the screen but actually look up information on papers, our credit card or read up the fine print that – of course – is not on the screen but only in the letter we got sent.
  • I have no clue how something like that works with switch access or voice recognition – probably not
  • It is scripting dependent – no JavaScript, no service

The latter is actually a reason for some companies for using this from time to time. Too many links on the same page are bad for SEO - Google considers your page not content but a sitemap and ranks it lower. That’s why some companies start offering the first two levels of navigation as links and the rest as a dropdown in this manner.

However, that still doesn’t make them a good solution, it just means that you offer far too many options to your users to begin with.

Here’s what people do to make this work: Aaron Cannon on the WebAim mailing list


A coworker and I recently devised a way to make a slightly more accessible version of the onchange dropdown navigation box. Basically, using javascript, we determine whether they are using their mouse or the keyboard to select each item in the list. If they used the mouse, it works as usual, immediately taking them to the selected page. If however the selection was made by the keyboard, we display a spinner and delay x number of seconds. If the user doesn’t make another selection within that time, they are taken to the page they selected. If they do, the clock is restarted.

I am not attacking Aaron here, he probably was asked to find a solution no matter what and did his best to find a technical way. The big scare in this for me is “determine whether they are using a mouse or keyboard”. My guess is they check for the event type, but assistive technology like voice recognition must simulate clicks without being a mouse. The other danger signal is the timer and the spinner – this complicates the interface even further (“Is this loading?”).

I simply don’t understand why we constantly try to make things work because this is what the design spec says or this is what we saw somewhere else. How about really testing it with users and see what happens then?

The Opera Web Standards Curriculum is live!

Tuesday, July 8th, 2008

The last few months Chris Mills from Opera was busy gathering a lot of great web development experts around him (with a lot of pimping by yours truly) to assemble probably the most thorough and up-to-date web standards curriculum on the web: The Opera Web Standard Curriculum

Several dozen articles, all licensed with Creative Commons will be available to cover the tasks of web development: from understanding the principles of the web up to Ajax interaction. During the whole course the main focus is on usability, accessibility and writing maintainable code. We deliberately left out browser hacks and backward facing solutions and build on the ideas of progressive enhancement and unobtrusive JavaScript.

I wished this would’ve been out when I started, it’d have saved me a lot of time learning bad practices and un-learning them (which is always a painful process).

So, read it, use it and teach younglings the way of the standards Jedi: The Opera Web Standard Curriculum

Making YouTube easier and more accessible (updated 12/06)

Thursday, June 12th, 2008

Warning: The YouTube API is flaky at the moment, so there might be some outages!

At this year’s Accessibility2.0 conference in London Antonia Hyde from United Response asked the audience for technological solutions to make the social web easier accessible for people with learning disabilities.

Her presentation Rich Media and web apps for people with learning disabilities is available on slideshare.

Whilst not being able to tackle all the issues mentioned (probably the biggest one being captioning) I took some time to play with the YouTube API to create a much easier interface to watch videos. The following screenshot shows the Easy YouTube Player in action:

Easy YouTube player showing a video

Using the player

You can use the player in several ways, the easiest is to just copy and paste a youtube url in the url field. However, there is also a sort of REST interface that allows you to do more:

http://icant.co.uk/easy-youtube/

Shows the player without any movie loaded, empty search fields and playlists.

http://icant.co.uk/easy-youtube/?http://www.youtube.com/watch?v=9i0-btCTdN8

Pre-loads the video of this YouTube address and shows the preview image in the player.

http://icant.co.uk/easy-youtube/?search=panda

Performs a search on YouTube for the term panda and shows links to the videos in the playlist on the right. You can use more than one search word by adding them with a “+”. For example:

http://icant.co.uk/easy-youtube/?search=red+panda

One last option you have is to bookmark certain videos on del.icio.us and tag them for a user. In order to show these videos as a playlist you need to provide your user name and the tag separated by a dash. For example my user name on del.icio.us is “codepo8” and I bookmarked some videos with the tag “easyyoutubeplayer”. The following link will show them all in the playlist:

http://icant.co.uk/easy-youtube/?tag=codepo8-foreasyyoutubeplayer

You can mix and match the different options. If you for example want to show a video and perform a search for other videos you can use:

http://icant.co.uk/easy-youtube/?http://www.youtube.com/watch?v=3UgpfSp2t6k&search=accents

Documentation

The full player documentation with instructions on how to host the player yourself is available in the docs folder Easy YouTube Player documentation.

Download

You can download the player with all the demo files here:

Changes

12/06/08

  • complete re-write of code
  • new buttons – glass were too complex
  • added video size control
  • added search and playlist support
  • added address field to send to friends
  • player now template driven – no more changes in main code needed
  • added documentation
  • added RESTful interface

28/05/08

  • moved buttons to the bottom of the player
  • text is now below the buttons and has an invisible extra “use this button to ” text for screen readers
  • pause button now toggles pause/play
  • mute button now toggles mute/sound
  • the URL of the buttons is not an anchor but a url now (that goes nowhere, but this is just to read out the right command)
  • removed the “current highlight” state
  • added a volume level indicator (as a visual bar and a hidden form field)

Fencing in the habitat – doing things right and getting the accessibility wrong

Saturday, April 26th, 2008

This is my talk given at AbilityNet’s Accessbility 2.0 conference in London today. In it I am talking about how we try to sell accessibility and the mistakes we make while we do so.

My wishlist for a great Ajax API

Tuesday, April 8th, 2008

Coming back from The Highland Fling it was interesting to see that people seem not to be quite convinced yet about the necessity of APIs and the large part they are playing in the next few years of web development. I guess this is partly based on experiences with APIs that aren’t properly explained to non-geeks and inconsistent or hard to use. There is just not much fun in trying to find information bit by bit if all you want to do is write some code (unless you have the old school hacker/cracker mind and didn’t consider spending hours looking at hexdumps trying to find a way to get endless lives in a games a waste of time).

During my interview with Paul Boag at I pointed out that designing a good API is as important as designing any other user interface – including your web page. Gareth Rushgrove agreed in his splendid talk How to be a first class web citizen. I also pointed out that there is a lack of clear and easy tutorials and articles on the matter, so I decided to have a go at it now.

Designing a great Ajax API

As an example I will use the recently released Google translation API, point out its good parts and list things I consider missing. I will not go into the part of actually writing the API but instead explain why I consider the missing parts important. This is not an attack towards Google, I just really liked working with this API and wanted to have it a bit easier to use, so no hard feelings, I really take off my hat that you offer an API like that!

Here are the points I consider important when we’re talking about Ajax APIs in JavaScript (Ajax implies that but you’d be surprised how often a REST API is advertised as Ajax):

  • Good documentation
  • Usage examples to copy + paste
  • Modularity
  • Link results to entries
  • Offer flexible input
  • Allow for custom object transportation
  • Cover usability basics

Documentation and presentation

Let’s start with a positive: the documentation of the Google Ajax Language API is great. You have all the information you need on one page including copy and paste examples. This allows you to work through the API online, read it offline and even print it out to read it on a crowded bus without having to take out your laptop.

Tip: If you are offering copy and paste examples – which by all means you should as this is what people do as a first step – make sure they work! I learnt the hard way in my book Beginning JavaScript with DOM Scripting and Ajax that there is nothing more dangerous than showcasing code snippets instead of full examples – people will copy and paste parts of a script, try to run it and either email you that your code is broken or – even worse – complain in book reviews on Amazon. If you offer copy and paste examples make sure all of them work independently.

Google offer explanations what the API is, what you can do with it, a list of all the parameters and what they mean. This is great for a first-glance user. For the hard-core audience they also offer a class reference.

Usage example

The first code example is quite good, you can copy and paste it and if your computer is connected to the Internet it will work – or it would, if the HTML got some fixes.

First of all it lacks a DOCTYPE, which is a bit annoying as it is a very important part of an HTML document. The more important bit is that the encoding is not set. The live example version has both – bit of a nuisance, as especially when we talk about different languages and using traditional Chinese as the example, the correct encoding is a must.

(Note: the irony, seems like wordpress doesn’t do this right for some reason …)







??????????



Tip: make sure you explain to people that your code examples need an internet connection and other dependencies (like requiring HTTP and thus having to run on a local server). JavaScript historically didn’t have any other dependency than a browser, this is changing lately and can be confusing, especially when you use Ajax behind the scenes like some Flash/Ajax APIs do!

Modularity is good!

The first bit that threw me off to a certain degree was the google.load("langage","1") line, but there is an immediate explanation what it means.

The first script include loads a generic Google Ajax API that has a load() method to add other, smaller APIs build on top of this one. In this case the line means you want to load the language API with the version number 1.

This appears clunky and you will get bad feedback for it (it seems there is nothing better the woo the masses to have a one script include solution) but is actually rather clever.

By modularizing the Ajax code in a base library changes to the core functionality will be easy and by asking the implementer to include the APIs he needs with a version number you can make it the choice of the implementer to upgrade instead of breaking older implementations or having to carry the weight of full backwards compatibility.

Yes, the perfect world scenario is that you’ll never have to change the functionality of your API - just add new features – but in the real world there are constant changes that will make it necessary for you to mess with the original API. There is no such thing as perfect code that is built for eternity. Using a loader function in the base API is also pretty clever, as it means that implementers don’t need to change URLs.

What goes in should come out.

This is where Google created a problem. Both the google.language.detect() and the google.language.translate() methods are quite cool insofar they offer you to send a string and define a callback method when the API returned a value. However, the returning object in both cases gives a result and a status code, but not what was entered. You get all kind of other information (described in the class documentation) but having the original entry would be very useful.

Why? Well the great thing about Ajax is that it is asynchronous, and that is also its weakness. It means that I can send lots of requests in the background in parallel and wait for the results. However, this does not mean that the requests also return in the right order!

This means that if you want to loop through an array of texts to translate, the following is an unsafe way of doing it:

var translations = [ ‘one’,’two’,’three’,’four’,’five’,’six’,’seven’,’eight’,’nine’,’ten’];
var gtl = google.language.translate;
for(var i=0,j=translations.length;i gtl(translations[i],’en’,’de’,function(result) {
if (!result.error) {
var container = document.getElementById(‘translation’);
container.innerHTML += result.translation;
}

});
}

Instead you need to wrap the incrementation of the array counter in a recursive function:

var translations = [ ‘one’,’two’,’three’,’four’,’five’,’six’,’seven’,’eight’,’nine’,’ten’];
var gtl = google.language.translate;
var i=0;
function doTranslation(){
var gtl = google.language.translate;
if(translations[i]){
gtl(translations[i], ‘en’, ‘de’, function(result) {
if (!result.error) {
var container = document.getElementById(‘translation’);
container.innerHTML += result.translation;
i++;
doTranslation();
}

});
}

}
doTranslation();

This is safer, but we lost the opportunity to have several connections running in parallel and thus getting results faster. If the result of the API call had the original text in it, things would be easier, as we could for example populate a result object and match the right request with the right result that way:

var translations = [ ‘one’,’two’,’three’,’four’,’five’,’six’,’seven’,’eight’,’nine’,’ten’];
var gtl = google.language.translate;
var results = {};
for(var i=0,j=translations.length;i gtl(translations[i],’en’,’de’,function(result) {
if (!result.error) {
results[result.input] = result.translation;
}

});
}

Even easier would be a transaction ID to pass in which could be the counter of the loop. Another option of course would be to allow more flexibility in the data that goes in.

Offering flexible input

Both the matching of the input text with the result and a transaction ID still would mean a lot of requests to the API, which is not really nice as it costs money and clobbers the server and the client alike. An easier option would be to not only allow a string as the text parameter but also an array of strings. The return then would also become an array and a lot of the overhead of calling the translation engine would be done on the server in a single call instead of lots and lots of API calls.

This is not hard to do and most JavaScript framework methods work that way, by checking the type of the first argument and branching accordingly. You can even go further and allow the implementers to send an own bespoke object as a third parameter.

Transporting a custom object allows implementers write a lot less code

The benefit of a custom object going out and in is that you can add more parameters to the API call that are only specific to the implementation. Most likely this could be a reference to a namespace to avoid having to repeat long method names or global variables. You could start by providing parameters that make sense to any Ajax call in terms of usability.

Thinking Ajax usability

The main thing any Ajax call should offer a user is a timeout. There is nothing more disappointing than getting the promise of a brave new Ajax world with much more interactive interfaces and then getting stuck looking at spinning wheels or worse hitting a link and getting nothing. Right now the language API has nothing like this, and you’d have to roll a solution by hand. You’d also have to check the error status code to see if the data could not be retrieved and call a failure case of the connection that way.

A nice API would offer me these options, most likely all rolled in one parameters object.

My dream translation API

Taking all these into consideration it would be perfect to get the API to offer these options:

google.language.translate(input,parameters);

The parameters would be:


input // string or array
parameters // object with the following properties
sourceLanguage:string,
targetLanguage:string,
transactionId:string,
customparameters:object, // to transport
timeout:integer, // (in milliseconds)
failure:function(result,params), // (method to call when there is a timeout or an error)
success:function(result,params), // (method to call when all is fine)

The returned data from the API should have both the result and the parameters provided. This would make the life of implementers dead easy.

Summary

In summary, here’s what I expect from a great Ajax API:

  • Have a good documentation with immediate copy and paste examples backed up by a full class documentation
  • Build your APIs modular and allow the implementer to choose the version they want to have
  • Provide a hook to link the result of the API methods to the initial data entered. The easiest way is to repeat this data, more sophisticated is to allow for a connection ID.
  • Allow for multiple values to be sent through, it’ll save you API calls and the implementer hacking around the problem of unreliable order of returns.
  • Allow implementers to add an own object to send and get back to allow for namespacing and other data state retention.
  • Allow for a timeout, connections are not to be trusted.

This is a work in progress

I hope you found something here to agree with and if you know things to add, just drop a comment.