Category Archives: usability

Offline Web Applications, we're not there yet.

Being able to use applications offline is an important feature in the quest for native like (mobile) web apps. The offline mechanisms currently available are indexedDB and appcache. Developers who’ve already used the latter know that it’s at least clumsy, and sometimes useless. If you haven’t, here’s why.

Use case, use case, use case

I want to create a mobile client for Twitter, no wait! I want to create a mobile client for Google Maps, no wait! I want to create a mobile news reader, no wait! …
Anyway, I’m a strong believer believer in the Open Web and a challenge taker, I don’t even want to use phonegap.
To display the home page and the different views of my app, I need a way to store the HTML, CSS and JS. To store the tweets, maps or news items of my app in a manageable way, I need a database. This content should be updated as soon as a connection is available; same goes for the HTML, CSS and JS that runs the app. More importantly: my tweets, maps or news items aren’t only text, I need to store the associated images or profile pictures.

What appcache offers

The main way to use the appcache is the cache manifest: a text file associated to an HTML page using the manifest attribute.

<!DOCTYPE html>
<html manifest="index.appcache">
<head>
...

The manifest itself consists mainly in a list of resources that should be cached and made available for offline use.

CACHE MANIFEST

CACHE
# resources listed in this section are cached
styles.css
script.js
jquery.js
logo.png

NETWORK
# resources matching those prefixes will be available when online
http:/search.twitter.com/*
http:/api.twitter.com/*

Here’s how a browser deals with appcache (simplified):

For more info, have a look at appacachefacts or the spec.

If the appcache has been udated, the browser does not refresh the page to display the new content. It is however possible to listen to updateready events and propose users to reload the page:

if (window.applicationCache) {
    applicationCache.addEventListener('updateready', function() {
        if (confirm('An update is available. Reload now?')) {
            window.location.reload();
        }
    });
}

Is that an acceptable user experience?
Having to do that every time the content of your app is updated is not acceptable (that’s why appcache should not be considered as a way to improve performances of normal websites). It would be acceptable if all the content of the app was updated using XHR, and only the structural HTML, CSS and JS was listed in the cache and updated occasionally (this would actually be a simpler update mechanism than the ones used by native apps). But current websites are usually not developed this way, as this can cause some accessibility and crawling problems.

Storing and deleting content

To store the content of my app in a manageable way, some kind of database is required. Luckily enough, IndexedDB will soon be available in the five major browsers. It will allow tweets, maps or news items to be first stored in plain text, as JSON or HTML; and later listed, sorted, updated and deleted.

What about the associated images?
That’s the tricky part when building a third-party app for a popular API such as Twitter or Google Maps: images loaded from a foreign origin cannot be turned to data-URLs for security reasons (unless they’re served with CORS headers, but they’re not; and using a server as a proxy to set CORS headers doesn’t scale, as those APIs have IP based usage limits).

Those images can still be listed in the cache manifest: a manifest server could be built to keep track of what should be cached for each user; it would dynamically generate a new manifest every time an image has to be added or removed; and once the new manifest is available, the client would do a applicationCache.update().
This is however absolutely unrealistic: First, a server is required, and that’s very much unfortunate. Then, when updating the cache, the browser throws away all of its current content and loads all resources again… This means that every-time a single image has to be added or removed from the cache, all other resources are downloaded again!

Can I build offline web apps, now?

App logic available offline appcache
Text content available offline indexedDB
App up-to-date when online appcache + prompt user to reload
Content up-to-date when online indexedDB + update using XHR
Foreign images available offline not yet

How should appcache be improved?

Content update

Yehuda Katz’s suggestion is to let developers specify that the manifest should be checked for updates before the page is loaded from the cache. If it has been updated, the page should be downloaded from the network.
This sounds like a good idea when XHR updates are not an option, and would probably yield good performances. I’m just afraid this could be abused by many websites just to improve web perfs, and users would end up with 1MB of HTML, CSS, JS and images on their disk for every site they ever visited in their life :-/
Ian Hickson suggested to rename the appcache to “offline application store”. Although this is unlikely to happen, I would also advocate using it only for offline purposes, and leaving caching strategies to the browser.
A compromise could be to adopt Yehuda’s solution, but always prompt users for permission to use the appcache. This should effectively prevent cache bloat. Not the perfect solution, sometime ago I actually opened a bug in Firefox to remove the user prompt: application cache should not bother users.

Dynamic cache

The best suggestion I’ve seen to address the need for a dynamic cache is the defunct DataCache proposition. The idea is to add an independant and dynamic cache to the static appcache, to let developers add and remove resources from the cache at will.
I confess I had trouble understanding all the details of the spec, but here’s a naive and rough API I’m proposing:

applicationCache.dynamicStore.add( uri );
applicationCache.dynamicStore.remove( uri );
applicationCache.dynamicStore.update( uri );

var cacheTransaction = new applicationCache.dynamicStore.transaction();
cacheTransaction.add( uri );
cacheTransaction.add( anotherUri );
cacheTransaction.run();

Of course, it should be possible to listen to events such as “updated” on applicationCache.dynamicStore.

This spec also introduces the interesting concept of offlineHandlers that allows XHRs to be rerouted to client-side functions when offline.

navigator.registerOfflineHandler( "search.twitter.com/*", function( request, response ) {
  // search for results in indexedDB instead
  ...
});

I definitely advise you to take a look at the code examples.

Conclusion

We’re not there yet and unfortunately I’ve got no ideal solution to the content update problem that provides both a good developer and user experience. “What Yehuda says + permission prompt” is the least worst option I can think of.
To make the appcache dynamic, I would strongly suggest giving a second chance to DataCache, and maybe simplify the API a bit.

The W3C will soon gather to think about the future of offline web app, so if you’ve got any valuable input, speak up!

"I won't make you click": exploring the potential of presentation on mobile

In one of my Master’s module, I designed and developed a script to display presentations on mobile devices (typically a smart-phone with a Web browser). The presentation was a simplified HTML file with all the slides stacked one on top of the other, each one displayed in full screen. It took me quite a long time to find a way to enable users to navigate through those slides and to get it to work on one device. Basically the world of mobile browser is a horrible mess, even when trying to work with Webkit based browsers, I was still facing some strange behaviors in the way events were handled.

I did manage to have it work on Android few days before the hand-in date of the project and realized that the result was not that impressive. In a corner of my brain there was the idea of using a mobile device to control a projected presentation. That seemed cool. So in 24 hours I read through the documentation of cometD, set up a server and hacked into the code (only the client side part) to get a functional prototype. It turned out that it was not only cool as my teachers thought that this was the main purpose of my project.

Anyway, time has passed and the cometD server no longer works, so I can’t produce any video to demonstrate it. However, while watching a video of Mozilla’s design challenge, I realized that my script required to tap the screen at least twice to navigate, when using only the native scroll of the browser was far enough! So I produced the first prototype of ToDoSo. Go ahead, give it a try. It won’t bite and I won’t even make you click!

I hope that this feature is not only cool, but also useful:

A presentation-assisted talk is in most case given in front of an audience, with the presentation projected in the back of the speaker. To be able to refer to his/her presentation, the speaker can use a remote control, which allows for moving freely but requires to turn back and look at the screen. Alternatively, the speaker can stand in front of a computer, allowing him/her to face the audience while restraining his/her movements.

A mobile device could take the best of both world if it was able to display a presentation to the speaker and control the slides faced by the audience.

First mockups and todosOverlay

The first two iterations of the management interface have been uploaded to the project homepage: todoso.org

This is the page that users will be facing once they are logged in: their most recent presentations are displayed and a search-box allows to search for other documents just like in gmail. It will be possible to filter the documents by tag, date or title. For example the query

date last month

will display all documents that have been created during the previous month. I’m going to try to leverage Ubiquity‘s fantastic natural language parser in this project and I hope to make this omnipotent search-box a first class citizen of the interface of the whole application.

When selecting a presentation, different icons appear for different actions that are yet to be determined (I was thinking about play, share, tag and use as a starting point for a new document).

I’ve also started to use the css framework oocss from stubbornella. This is a really easy way to make a first step into the world of css frameworks and the focus on performance of this project doesn’t let you any reason not to try it.

Finally, facing the lack of an elegant and light-weight image overlay solution (commonly known as lightbox), I’ve started my own which is really simple but not yet really flexible: todosOverlay. It’s simplicity is a direct consequence of the exclusion of IE6. I’m pretty sure we could enter into a virtuous cycle with this browser:

The less support we provide, the more users are facing broken Web sites, the more likely they are to figure out that their is something wrong, and they’ll be in turn more eager to switch to a better browser, the less we’ll need to care about providing support!

So, what is great about this “yet another overlay plugin”?

  1. it requires only four files:
  2. which have altogether a really small file size
  3. it looks beautiful in the latest versions of Firefox, Safari and Chrome thanks to the border-radius and box-shadow CSS3 properties, it looks Ok in Opera, IE7 and IE8.
  4. just like the rest of this project, it is Free Software and all the SVG sources are included. Therefore you can really adapt it to suit your needs and desires (changing the color of the close image for example).

What might not please you in its current state:

  1. the overlay doesn’t scroll with the page,
  2. the overlay has a fixed size and the inner image is scaled,
  3. you cannot add text to the overlay,
  4. you cannot switch to the next/previous directly from the overlay like you can do with jQuery lightBox
  5. there can be only one overlay at a time on the page

How does that work?

[code lang="js"]
// The plugins has to be set on thumbnail container
$("#myThumbnailContainer").todosOverlay();
[/code]

It is currently possible to change the size of the overlay (its width, the height is calculated according to the thumbnail dimensions) and to change the regex used to find the full size image based on the thumbnail’s url. If the thumbnail is:

http://www.example.com/images_200px/myImage.png

and the full size image is:

http://www.example.com/images_500px/myImage.png

you can use the following options:

[code lang="js"]
$("#myThumbnailContainer").todosOverlay({
width: 500,
regex: /_200px/,
replace: "_500px"
});
[/code]

By default the plugin will search for any “_thumbnail”, “thumbnail_” or “_thumbnail_” string in the url and remove it.

By the way, I tried to use picasa as a CDN for the pictures on this site, and it turns out that it is not possible. For some reasons, the pictures sometime refuse to load: the address is correct, the thumbnail even appears in firebug but the load event never triggers… I just gave up. If you want to give it a try, the options for picasa are:

[code lang="js"]
{
regex: //sd+//,
replace: "/"
}
[/code]

Project Renaissance: about OpenOffice.org and usability

I’m still working on formal specification for my project but I can post about interesting things I’ve discovered along the way: Project Renaissance.

In brief, project Renaissance aims at improving the user experience with OpenOffice.org products, which is well summarized by the project’s motto:

“Create a User Interface so that OpenOffice.org becomes the users’ choice not only out of need, but also out of desire”

From my point of view it seems like a good start! Even though the project’s homepage show already some flows, such as the Project Charter being spread across different pages when one would have been much more effective… Let’s not be picky and see what is going on:

The first phases of the project consist of surveys to better understand the needs and desires of the users and involving the community with a call for mockups for the future Impress (which is an application that appears to be important for users and where there is obviously a lot of space for improvements). Those mockups can be reviewed in slides 21 to 34 of this presentation. I don’t really like any of them : / But remember that they are only ideas of interested contributors, they are just personal contributions to a greater goal: making Impress better for everyone.

There is also a Blog for this project that gives a better idea of the progress being made. It is just a shame that it gets so little visibility… or is it just an impression? Anyway, the first benefits of renaissance are expected to make their way into OpenOffice.org’s products for the version 3.2 which is expected… when it is ready probably. I’ll be happy to see what this great project come up with, I’m sure that my application will be very different but only the future will tell which approach is the best.

At the same time I discovered about another interesting and Open project: Interaction-Design.org and particularily its encyclopaedia available under a Creative Commons ShareAlike license. The quality of the content seems satisfying, I’m sure everybody could learn something. In the article about Mockups, I really liked the following idea:

“Mock-ups incite criticism from users because they are low-cost (can be made of cardboard) and low-fidelity. If a user is presented with an early version of a system that has required substantial work, he/she is likely to be more reluctant (as well as able) to criticize it.”

I’m personnaly always trying to create visually appealing mockups because I am afraid that the very first impression might have a bad influence on the user’s general opinion. My perfectionism is once again playing a trick on me…