Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2009-203
$eventId
ID of event: wwdc2009
$eventContentId
ID of session without event part: 203
$eventShortId
Shortened ID of event: wwdc09
$year
Year of session: 2009
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2009] [Session 203] Local Data ...

WWDC09 • Session 203

Local Data Storage and Offline Web Applications for Safari

iPhone • 48:17

Web developers can now create web applications that you can use even when you don't have access to the Internet. Discover how to cache web applications and store data locally so that the application is always accessible. Learn how to employ the latest HTML 5 offline storage technologies including simple key/value storage, local database storage for complex structured data, and application cache storage for your HTML, JavaScript, CSS and other webpage resources.

Speakers: Brady Eidson, Beth Dakin

Unlisted on Apple Developer site

Downloads from Apple

SD Video (129.2 MB)

Transcript

This transcript has potential transcription errors. We are working on an improved version.

My name is Brady Eldson, I'm a software engineer on the Safari and Web Kit team. First I want to ask you a quick question. How many of you have developed real applications for the desktop. A lot of hands. OK. How many of you have developed web applications that run in a browser. A lot of the same hands. And for that one guy way in the back who didn't raise his hand for the web app question, I'm going to talk about really quick what a web app is.

The web started out with single web pages. Throw some HTML up on the screen, some images, some bouncing marquees and banners and call it a day. After a little bit we started to get what we call web sites, collections of pages on the same topic that were -- the same kind of methodology, just throwing it out there and making things a little more complex.

As browsers and web technology evolved, things started to get a lot more organized, a lot more dynamic, and we started to call these collections web applications. Now with modern browsers and modern standards really turbo charging what these web applications can do. So it's a lot more like what you desktop application developers are used to developing. With technologies like font face and SVG fonts, and great new text editing APIs. Rich media, and desktop-like UI experiences with the audio and video elements, and accessibility support.

All the cool image effects and graphics effects you can do with CSS masks and transforms and gradients and animations, all that cool stuff. The data of the application yourself, we're giving you the turbo charged nitro JavaScript engine, and we're giving you great developer tools to make developing a web application feel a lot more real.

But there's been one thing missing here. What about the data. Some of you might be saying what data. Well, what about your application's data, the state of the application, where in the middle of a long running procedure was your application, what was it doing, where were the windows, how were they set up. How about the resources to make up the application itself.

Your markup, your style, your scripts, and then there's your user's data. Your users probably have a preferred way of using or viewing your application. So all their preferences and settings. And in many of your applications your users are generating content right there in the browser. So all this data has to go somewhere. And typically it's been on a server somewhere, right? The application resources themselves, they come from a server, and then we're used to shipping data back off to a server.

Well, users have machines. Sometimes they're brand new hot machines, sometimes they're machines that have been around a little bit. And the machines really take all sorts of forms, right? And all these machines have something in common. They all have some sort of local storage. Disc drive, solid state flash drives. And we want to give you a standard way to access that and use it to its full potential.

Standard way. We love working with web standards, Apple work, has been working closely with the WHAT Working Group in W3C on the HTML 5 standard. And we're trying to bring these technologies forward in Safari and in a standard interoperable way that hopefully everyone will be implementing. And everything I'm going talk to you about -- to you today, is available in Safari 4 that was released on Monday, on Mac, on Windows, and in iPhone OS 3.0.

So we're going to talk a little more about data on the web. We have some new solutions, but this is an old problem. So we're going to talk a little bit about the ingenious ways you as developers have been managing the data so far. Then we'll jump into our first standard, the HTML 5 Key/Value storage.

It comes in a couple flavors that do a couple cool different things. Then we'll get into the power of the HTML 5 structure databases, some really cool, powerful stuff. A relational database in the browser, accessible through JavaScript. And then we'll cap it off with a little discussion about the HTML 5 application cache, which is all the resources that make up your application living in a predictable way inside of your user's browser. So data on the web. Right now there's all this data flinging around. I've gone over most of it, the application resources, the data your application needs, the data your users generate.

And there hasn't been a good solution for how to wrangle all this data. You as developers have come up with some pretty creative solutions in the meantime. Ways of handling the data in the absence of a better alternative. For example, cookies. Cookies were invented as part of the HTTP spec for shipping data automatically back and forth between the server and the web browser.

They're great for that, they'll always be great for that. But they're more fragile than some of you might think. The cookie standard says that a browser can be very limited in the cookies it supports, it can prune them any time. You might set an expiration date far off in the future and assume it will be there years from now. In most cases, it won't be.

There's severe limits on the sizes of cookies, and they're just too limited and fragile when it comes down to it. What about the cloud. Sending data through the Internet to a server somewhere that you control. This is very important, and it will continue to be important, using form data to post, using query strings in URLs, or shipping data off with an XMLHttpRequest to a server you control.

The problem here is the network is fundamentally unreliable compared to knowing what's going on on the local machine. The network is slow compared to how data is transferred around within the machine. You have to control the server. You have to manage it. You have to keep it up-to-date. And really, it's just too complex and expensive for a lot of the solutions you as developers really need to -- really need.

And then there's plug-ins. Many of you have turned to some popular plug-ins, some unpopular plug-ins, and sometimes your own custom plug-ins to store small nuggets of data in the user's web browser, or to store large volumes of data. The problem with plug-ins is that they don't integrate into the browser very well. Each plug-in has their own UI that the user has to access outside of the browser standard UI. Plug-ins might have different bugs on different platforms.

And if they do have different bugs in different platforms, you either have to be in control of the plug-in and debug on all the different platforms, or you have to talk to the vendor, and some users might not have the plug-in, and some users just don't want to browse with plug-ins, and some plug-ins may be slow to load out of the browser space, and there's just all these problems.

They're just not standard web technology. Some of you might be overwhelmed right now. You're saying to yourself, I never thought about it all that way. What should I be looking for. When we're manipulating simple data, what's an ideal world. Manipulating simple data should be fast and it should be easy. Back to the cookies example, where we're storing small nuggets of data in cookies.

How many of you are familiar with writing a cookie parsing string just to get a document.cookies. See a few hands come up. Have fun with that, some time, if you haven't tried it. It's ridiculous just for Key/Value pairs of data. So it should be a lot easier than that. And then with more complex data, we need to be flexible. We need to be able to handle any size of data, any complexity of data, data with structure.

And it needs to be just in a built in native way in the browser, standard -- standard base way, hopefully. And it also needs to be fast. Modern users aren't going to wait for anything, in the web browser or on the desktop application, it's the same to them. If your page is locking up the browser or taking a long time to complete something, they're not going to put up with it. So even large amounts of complex data needs to be fast.

And no matter what kind of data we're manipulating, it needs to be persistent and secure. We need to know if we want it to be there ten years from now, it will be there ten years from now. It needs to be secure. We need to know that our web application and our users are in control of our data, and are the only ones who have access to it. So with these things in mind, I'd like to talk to you about the HTML 5 Key/Value storage system. Key/Value storage is about a simple way to manipulate simple data in JavaScript in the browser.

Data that will be persistent and accessible to you a long time from now and off line with no network required. In the Key/Value storage API, data items are Key/Value pairs, much like in a cookie string, or if you're familiar with using LocalStorage in Flash, for example. It's the same type of data.

And it's really simple to manipulate. The way the Key/Value storage works, and I'll get into it in just a minute, it just integrates into the JavaScript language natively. It feels like -- you're just using JavaScript. If you know how to use JavaScript you already know how to use Key/Value storage. So it's really great. It has origin-based security. This has been the standard security model on the web and it's being really formalized in HTML 5.

All this means is that documents and web pages from your web server, your domain, HTTP, your protocol, your port, they are the only ones who can get at this data. So if you set a Key/Value pair item, you will be the only one who can get at it later. It comes in two varieties, which I'll go into a little more detail on shortly. The SessionStorage and LocalStorage. They attack two different problems, and together they really replace both plug-ins and cookies for manipulating any simple data you have to throw at your application.

And finally, it has some events. So you can listen to changes in the keys and the values in different documents different frames, and really keep things in sync. So what are these two mysterious things I've touched on a couple of times now, the SessionStorage and the LocalStorage. These are the two objects that you'll access in script to get at the Key/Value storage API.

Each of them does something different. SessionStorage. Now I was booking a vacation earlier this year. I had a couple of weeks off. I wanted to go to Boston, I wanted to go to Paris, I wanted to go to London. I opened up my favorite travel web site in a couple different browser Windows, found the perfect flight to Paris in one, the perfect flight to London in the other, and then I clicked purchase on both and checked my e-mail and I was the proud owner of two tickets to Paris.

What happened? What happened was they were using cookies to manage my session. Now a lot of the time this is important to manage a session between the browser and the server. But when the session is only important within the browser, they're overkill, and they have this fundamental problem is that they're global. So SessionStorage replaces cookies for session tracking, and the way it does this is by giving you one session per browser window per browser or tap.

So I would have gotten one ticket to Paris, one ticket to London. I would have been on my way for two weeks of fun instead of one week of the same fun twice. And the LocalStorage object is using the same API to persistently pin down some data inside of the browser.

It is persistent on the disc, on the Flash device. It is global. SessionStorage is per browser tab or window, LocalStorage is accessible in every browser tab or window. Quite deliberately. So how do we use it. SessionStorage, for example here, the exact same API for LocalStorage. Call set item.

First argument is the key, second argument is the value. Or you can use array property access in JavaScript that you're probably familiar with to do the same thing. The key inside the brackets equals the value. Or.property access, if it's a static property that you know beforehand. All these three statements right here do the exact same thing. Just integrates right into the language, getting at an item, exact same thing in reverse.

You can iterate over all the items in either the SessionStorage or LocalStorage object using a standard JavaScript loop, four loop. You can use get item here or the bracket property access. You can remove items with removeItem, or built right into the language, go ahead and delete the property off the object. You can clear the entire thing out in one fell swoop with the clear method. And that's it. We're on our way, storing simple Key/Value pair nuggets of data in our user's browser.

Now there's the events I mentioned earlier, they're kind of cool. They help you keep tabs and windows in sync, like I side, whether it's within one tab or window for SessionStorage, or over all of them for LocalStorage. They set whenever any item changes. So when you set a new item, when you change it, when you delete it.

And it's sent out to keep different documents in sync. And it's sent to all the documents that are open in the web browser with the same origin, the same domain that you control, that your web app is served from. And like I mentioned, with SessionStorage it's sent to each frame in the current page within the current session. And with LocalStorage, to every frame in every page, because everyone can get at LocalStorage. The event has -- oh, I'm sorry, to listen to the event at event listener, the name of the event is storage.

Or you can go ahead and use the on storage attribute on the body element. And once you have the event it has everything you need to know about what happened. The new key -- I'm sorry, the key, the old value, the new value, and then you can find out a little bit about where the event was generated from.

And that's it for the entire API and the entire event system, SessionStorage and LocalStorage. It's so simple to use, builds right into the language. It's a great tool. To show you a demo of something that we've been working on, I'd like to invite my esteemed colleague Beth Dakin up on stage.

[ Applause ]

Thanks Brady, that was great. So Brady and I love playing checkers. We play whenever we have free time. We play on evenings, weekends, we play on lunch breaks, holidays, we are 24-7 checkers playing fiends. So we decided to get together and write a little checkers web application. So I'm going to show you what we have, and I'm going to tell you how we want to enhance it with LocalStorage. So let me see.

There we go. OK, so here's our checkers application. And I'll give you a little tour. Down here we have turn indicator lights. So I'm blue and I go first, and the computer is green. And then we have a few buttons down here. The first button is a New Game button to start a new game at any point.

And then these other two buttons represent the LocalStorage features that we want to add to our web application. First is the Manage Games button, which will autosave games as we play using LocalStorage, so they will be saved locally on the machine. And you can manually save a game at any point and have a copy stored locally.

And then the High Scores button will keep track of high scores as you play over time. So you will have a copy of that data, and you can see how you improve over time. So the game itself, we made it kind of extra fun with these CSS -- sweet, achievement unlocked. We made it extra fun with all these CSS things and -- oh man, that was such a stupid move.

Brady, I wish that we had implemented saved games already so I wouldn't have to look like an idiot in front of everybody. I was playing earlier today and I was doing so well.

OK, so Beth, actually last night after we finished playing, like, at midnight, and we had gone for three hours playing checkers, I actually took a few minutes before going to bed and actually implemented the Auto Save feature.

No way.

So your game from earlier today might actually be there.

Oh my God. There it is. From 10:56 this morning. And here is an autosaved game from me playing just now. That is so sweet. How did you do it, Brady?

Well, you've got the code. I think you probably know where I implemented it. Go check it out.

True, true. OK, so I'm guessing that Brady did this in our game_manager.JS file. And yes, sure enough he fleshed out our save and restore functions which were empty before. And you can see it was this simple for him to save a game. He just had to add a few Key/Value pairs to the LocalStorage object. Just enough data to fully restore a game.

So you know, the first one you can see is he takes player 0 and stores an array of the positions of all of the board pieces, the checkers, at that time. And then a few other pieces of information, like the same data for player 1, enough data to restore the game.

And then the restore function just retrieves that information from the LocalStorage object, and does the right thing with all of our member variables to get everything in the right state. So let's load that game. I was doing really well. Yes! All right, and now just to show you -- I can manually save this game too. So now I have another copy of it there. And I'm just going to play a little checkers.

And I won. Yes!

[ Applause ]

OK, so you can see that here this immediately brought me to the High Scores page. And it put in my awesome game data for me to remember. But we haven't implemented high scores yet, unless Brady did that last night too.

I had to go to sleep and be refreshed.

I didn't think so. So as soon as I close this window or navigate away from the page, open a new window, go back to my checkers game, that data is lost.

So let's implement high scores right now, shall we? So I'm going to go to my high scores.JS file. Here we're doing all this stuff to pop up the panel that contains all the data. But right now as you saw, that data is lost once we start a new session. So set score.

Let's do that first. Have it over here. OK, so here we just have a very small function, again, where returning early for browsers that don't support LocalStorage. That's just a good backwards compatible move. And then down here we're just storing the name and score in the LocalStorage object, and then load score which will be called wherever we show that panel, the high scores panel, we just need to retrieve that data. There we go. So let's see this in action. Oops. Let's refresh my board.

Let's go back to that sweet game. I'm going to try to save this again. OK, now if I close the window, open it again, go back to checkers, then my high score is saved for all eternity.

[ Applause ]

And you know, that's all. Just to implement those two really cool features, to add them to my web application, just a few lines of code. So back to slides.

Thanks, Brady.

Thank you very much, Beth. So that was pretty cool. So now that we have those implemented, when we're playing one on one we can compare our results later and continue the argument about whose better at checkers. So -- so what Beth showed you is that LocalStorage just integrates right into the language. We used a few different forms of accessing LocalStorage. I prefer the array property access. They all work the same.

But it just builds right into JavaScript. And really, we're saving the application state locally. That's the key. The high scores, the saved games, where the user is in the middle of the game. We can quit the browser, come back, it's stored there in a predictable way on the disc, it was all done just using straight forward JavaScript. That is Key/Value storage in a nut shell. New HTML 5 standard, standard way to manipulate data in the browser.

But some of you have different kinds of data. More complex data. You have data with structure. You have relational data and you have massive amounts of data. So what can we give you? We can give you the HTML 5 structured databases. These are a database inside of the web browser that you can use to store complex data off line.

For example, let's take a look at a calendar. This is one type of data we might want to enhance using databases. We have a lot of different events, each event has a lot of rich data. We have relationships between the events, we want to select from different calendars for different types of views. This is a Mobile Me calendar, it does not have this feature. But last year we implemented an off line calendar.

It's available on webkit.org if you guys want to check it out. It does have this feature. We're storing calendar data off line and it's just really easy to enhance features of the calendar by using database queries on the data. And it's all written in the same JavaScript most of you are familiar with.

A mail application. Another type of data that would -- is commonly used in a web application that could be enhanced by storing or caching a local copy of the data inside of the user's browser. So structured databases HTML 5 standard way to do all of that. And it is real-world SQL.

The same SQL that you're used to using -- many of you anyway, are used to using on your web servers in applications using database programming. It is the real world SQL that you're familiar with. Is asynchronous and callback-based. Remember, two things are very important to us. I'm sorry -- one thing that is very important to us was the speed.

Was making sure that the user never feels our pain as developers of wrangling lots of data. So the way we achieved that with the database API is by making everything callback based. So it's running in the background while your user continue to interact with your web application. It has the same origin-based security, that is the standard security model on the web.

And that is very explicitly defined in the Key/Value storage. This means the same thing, documents from your domain have their own set of databases that they can access and no one else can touch them. So I kind of tried to reiterate on this point a little bit. What do I mean by real world SQL. I mean real world SQL.

There are tables. There are rows of data. There's definitely indexes, you bet there's triggers, and there are transactions. They're built into the API. We do not let you forget about the transactions. They're important to keep things fast and keep things efficient and the database small. So what are some advantages of storing our data locally. Well, first off, it works off line, right? That's the key of this talk, the off line data aspect.

A lot of the time, in fact, most of the time, table, it's still going to be very important to ship data back to a server that you can control, so it's accessible from multiple places, multiple browsers. But I bet a lot of you can find a lot of ways where it makes sense to store and cache a local copy of the data inside of the browser. And that data will be available off line. You won't need a network connection to any server to get at all this rich data. What about some performance enhancements we get from doing this. By keeping the data local we get a great speed boost.

For a lot of the time when we just need to cache data, or just need to perform a local query on data that makes sense that we have cached locally, when we take the network out of the equation, that's just a fantastic boon for performance and responsiveness. Take the latency out of the question. And for battery life. We have notebooks, we have the iPhone, and other mobile devices that support this.

Take the network out, take the radio out. That's fantastic. And in the cases where it makes sense to cache some of the data locally inside of the browser, there's less complexity. We don't have to set up a connection to the server using your favorite flavor of connection, be it a host or an XMLHttpRequest. Taking that out of the equation and just running the SQL right on the -- right on your user's machine can help take a little complexity out of the equation.

So back to the mail example. You know, I ride the train to work many mornings, and a lot of the times there's no network connection, be it on my phone because we're going through tunnels or we're in the middle of the wilderness, the trains around here don't necessarily have Wi-Fi yet. It's sad, being Silicon Valley and all. But it's coming.

But until then, I want to download my mail at home, hit the train, and then be able to compose replies on the way to work, for example. Very important replies, about pictures of cute puppies and kittens. So let's talk through how we might augment a mail web application to do something like this. The first -- this is just going to be a scrape of the surface of the database API.

But we're just going to walk through the workflow of how you might use it. So first we're going to need a database handle This is the entry point into the HTML 5 database's API. There's an open database method on the window, called an openDatabase with a few nuggets of data, and you have a database handle ready to go. The important piece of data here for all of you who just want to cut to the chase is the name of your database. Your origin, your dmain that you control has its own set of databases. And you can create individual named databases within that set.

So here we're going to go ahead and call it off line mail. So we have our off line mail database handle. The entry point into actually doing something with our database handle is the transaction method. Like I said, transactions are built into the API. We do not let you ignore them. And they are how you get things done. And this is also the first time you're going to see the callbacks I was calling about.

This API is asynchronous and callback-based. So you will often be passing in JavaScript functions as callbacks for the browser to notify when certain parts of the database operation are progressing or complete. The most important one here. You can go ahead and ignore the error callback or the completion one. The most important one is the transaction callback. When you call database stop transaction you're getting a transaction object that is a guarantee that you're ready to go, performing SQL queries inside the database.

Here's an example of a transaction callback. Given the transaction object. I have some SQL to run. And now for the first time in this chain of events I am actually running an SQL query inside of the browser using JavaScript. I'm going to go ahead and create a messages table in my off line mail database here.

There is an alternate form of SQL for arguments. As you know, the database sanitization considerations, a lot of the time we want to put place holders in our query, we use question marks for the place holders. That's written into the standard. And then for each question mark you have, you pass in an array of arguments and each member of the array replaces one of the question marks.

So now we're actually putting a message into our database. We need to get stuff out of the database, of course. And the way you do that is with the very important statement callback. This is another form of SQL, and when you expect to get results out, you need to pass in a statement callback function.

When that SQL statement is done executing, this callback will be called with the results that were pulled out of the database, if there were any. And it also gives you a chance to continue a chain of statements in this transaction. So that's it. Like I said, I was scraping the surface of how the database API works.

It is a rich API, and I just want to give you a sense of the flow. To really understand it and to get to know it well, it's great to look at examples. This is the off line calendar that we implemented last year. It's now available on webkit.org. And it has a lot of great code you can look at. This is all what has now become a semi famous example, the sticky notes, which is probably overkill for database usage.

But that makes it a great educational example because it's really simple to see where the database operations fit in to just creating and editing sticky notes. Now many of you that are familiar with database programming sometimes like to get down to the metal and log into the database and just run queries directly. Not in code, just tinker around in the database and know what's going on. And Safari's great web inspector will let you do that.

In the web inspector there's this -- let me back up there. There's this databases panel. Any time you are at a page that has databases you can go in and click on the databases tab and see what's going on there. It will just give you a view of the first few rows in the database to see what the -- what the rows in the table are, what data is in there right now. It's pretty cool.

And then like I said, you want to get down to the metal and run some SQL queries, and the inspector will let you do that too. You can see here, we're playing around with our Web Kit sticky notes example, and we're just poking around in the database, just like any other SQL database.

Pretty cool stuff. So that was an overview of the HTML 5 structured databases. Like I said, those great examples are great to look at. And you can look at the documentation to really flesh out your understanding of it. But it is a standard way, HTML 5 standard way to manipulate structured relational data inside the web browser.

Some of you might be asking yourselves well, what else can I store off line. I'm storing simple Key/Value nuggets of data with using LocalStorage, and I'm storing rich structured data using the databases API. Is there anything else I could do. And there's something very important you could do.

And that is the HTML 5 application cache. The application cache has really caught on since we introduced it in the Safari 4 developer preview last year, and other browsers are starting to implement it. It's a fantastic idea. It's storing all of the different resources that make up your application off line. The mark up, the style, the scripting, the images and other media, storing them in a reliable manner inside of the web browser, so that the web browser knows how to load your web application, even when the network is completely absent.

The application cache requires you to put together a manifest of resources. It's a list of all the different URLs that go into your application. That's a new object that you can poke at and tinker with to monitor how the application cache is working. It's -- it's a simple object, but it gives you some important insight as to how the mechanism is working.

I'll touch on that a little more later. And importantly, to me, anyway, and a lot of the developers that we've heard from, the application cache has an automated atomic update mechanism. Automatically, when a network connection is available, the web browser will go to your web server in the background, see if there's an update to your web application, and start downloading it in the background.

And then when it's time, it will perform the update atomically. In college, a lot of times I was editing really complex web sites and you know, refresh things in the browser, and things were all broken to hell, because it got Version 1 of one file, but Version 2 of another file. Application cache would love to just get rid of that problem. The updates will be atomic in a predictable manner. And finally there's also a mechanism to monitor on line and off line status.

So you know when you have that network connection and when you definitely don't have that network connection. Because a lot of the time, a web application why trying to behave like a full-fledged first-class citizen desktop application really would like to change its behavior based on whether it's online or off line. Present a different UI, take certain features in, certain features out.

So now we can start to do that in a pretty cool way. So this resource manifest. Let me get back on this. This is a pretty important part of things. It is a text file. It is a text file that has a list of every URL your application needs to operate. When you're using the application cache mechanism you're opting into an alternate loading behavior of the browser.

The standard loading model does not apply any longer. And one important thing here is that every URL your application will ever need needs to be listed in the cache manifest. With many applications that have been constructed with modern web practices and the future of the web in mind, this is easy. Sometimes it will require reworking the application a little. But it is important that you list every URL. Any URL that's not listed in the manifest will not be accessible from your web application.

As two types of entries, the explicit entries, these are the cached entries, these are the things we know we want to store off line, to be available all of the time no matter what. And then it has the online white list entries. Because we usually do have a network connection.

And we do have to list every URL that our application might need, we need to list the URLs that should always go to the network, so they are accessible to our web application. Here's a sample manifest file. You always start it off with the big all caps phrase cache manifest.

And then you just start listing URLs. Here's the cache section, this is the explicit section. Also, it's the default section You can leave cache off if you want to. You can see here I have a relative URL, I've got a fully qualified URL. I've got a few different kinds of resources that make up the application. And I can even grab an off site URL if I'd like.

So any standard web site you could build here using resources from different domains, you can do that using the application cache as well. And then we have our network entries, the dynamic things, the things it doesn't make sense to store off line, and we always will need a network connection to use. And that's it for the text file, that's a list of URLs. How do we get this into play. How do we tell the browser, hey, I'm a hot new developer who is using this great new application cache feature.

I want you to go ahead and get it from my server and start using it. I introduce to you the HTML element. The loneliest of all elements, with no official specified attributes until now. Specify the manifest attribute on your HTML at element. Point it to the manifest file on your server.

And you have now opted into the application cache mechanism. With one more caveat. You will have to tweak something on your server. The server will have to send explicitly the text cache manifest mime type for the manifest files. This is an explicit thing that we're very deliberate about opting into.

Which is why this is required in the spec. So the loading process changes. I mentioned this a little while ago. What is the new loading process when you're using the application cache. When your users visit your web application, the URL for your web application, the web browser will load all the resources from the local cache as copied.

It won't even try to get them from the network. However, that automated update process will kick off the moment they visit your web application. Safari will refetch the manifest file in the background from your web server. And if it is changed, it will start revalidating all the resources that it's caching locally off line and download them as necessary.

Now when the update is complete, when the new manifest has been registered and we've downloaded all the new resources and we have our own off line copy, you can call a tiny little JavaScript, which I'll show you, to right in place switch your users over from Version 1 to Version 2 of your app. Or the new version will be available the next time they visit your site.

So the way you do the atomic update explicitly, so you can use that application cache object, and listen for the on update ready event, and pass it an event handler, and then you just go ahead and call swap cache . And now you've just in place slid your users over from Version 1 to Version 2 of your application. It's pretty cool. Will -- like I said, will happen automatically if you don't do that, so you don't even need to do this.

You can listen to a lot of other progress events about this automated background update process. So in case you want to -- your application is huge and complex and you want to present a UI, or you want to monitor the progress for your own error handling or statistics gathering, you could go ahead and listen to all of these great things.

I'm not going to go into detail on them now. But the documentation on application cache will tell what they do. And then we have these online and off line events, and the status in general. There's window.navigator on line. It's a new property on the navigator that will tell you, hey, am I on line or am I for sure off line. Go ahead and add an event listener, in case you want to monitor as the network connection status changes.

One use we've seen is when the device, the -- your user's machine, whether it's an iPhone or a desktop or a notebook, when it gets back on line, you'll kick off the update mechanism manually, even though it's automatic when they visit the URL, you can manually kick it off if you'd like.

So it's pretty cool. That's the application cache. A standard way to store all of the different resources that make up your application off line, inside of the web browser. Now to show you further augmentation we can do to our way sweet checkers app, I'd like to invite Beth back on stage.

Beth?

[ Applause ]

Thanks, Brady. So we have this problem. We just made our checkers web application pretty recently, and it's a lot more popular than we expected. And we have kind of a crappy server, you know, not great bandwidth. So we're having this problem where a lot of our users are complaining to us that there's a lot of lag during peak checker playing hours.

So this is a real problem for us that we want to address, but we don't really have money to throw at the problem right now and get a better server or anything. So we think that a great solution in the meantime is off line checkers. It will make things faster for our users, and they won't even know what kind of magic we're doing under the covers. And really, this isn't a meantime kind of thing. This is a really great feature all the time.

It's great on the desktop, but it's particularly compelling on the iPhone. Because on the iPhone you often find yourself with a really low bandwidth network situation, like on the beach in Barbados, or in a no network situation, like on the plane to Barbados, and in these situations you want to be able to be playing checkers.

So let's implement off line checkers right now OK, great. So as Brady said, we need a manifest file, which we already put together here. And we also already took care of tweaking our server. So the one last thing we have to do is include the manifest attribute in our source file.

Oops, wrong spot. There we go. Save that. Let's open our checkers game. Reload it. OK, so the first load was a regular network load, and this is an off line load, and you'll see that I am actually missing a resource here. So even though I have network enabled right now, I must have missed that resource in my manifest file. And because I missed it, then it won't load. And yes, it looks like I only have one turn indicator light here. And I'm supposed to have another one for player 0.

So let me fix this. Oops. Save that. Let's reload. There we go. So with the reload, I have my turn indicator light, and I have off line checkers. And I can still play with it and everything. I can still access all of my saved games, see my high scores, and it's pretty sweet.

So now let's take a look at it on the iPhone. All right, so first I'll take us into Safari where we can load it there. So here's my checkers game. I can play it like always. Yes. It's always exciting. So -- but now let's check it out in airplane mode. And I saved this web application, so I'm just going to load it again. Now fully in airplane mode without any network. All right, reload. I can still play my checkers game.

[ Applause ]

I can access all of my features here too. And that's it. Just editing my HTML in one spot and doing a couple of other little things, we have off line checkers.

Great, thank you very much, Beth.

[ Applause ]

So with the way we developed our checkers application from scratch, it was really just a matter of listing all the URLs in a text file to make it work off line.

This gives us a few benefits, like Beth said. It not only works completely off line, like in airplane mode, or in low bandwidth mode, like on the beach in Barbados, but even when a network is completely available. We're saving server bandwidth, right? We're avoiding a hit to the server for all these different resources, no matter what the HTTP caching mechanism we wanted to put in place was. And it's a better loading experience for our users as well.

Which is exactly what I just said, speeds on line loading. And I already said that at the very beginning too. Just a few steps to add. Now one thing we didn't show in the demo is we had already tweaked our Apache server. So don't think that I said you have to do that, and then we left it out, so maybe I was lying to you. That is important, so we did do that. But otherwise, just -- that manifest file, and we're good to go with our off line checkers.

That's all I have to talk to you about today. Talked a little about the -- little bit about the current state of data on the web, an old problem that we finally have new solutions for. And we went over those new solutions. The great HTML 5 standard Key/Value storage integrates into JavaScript beautifully.

The structured databases which gives you the power of an SQL database inside of your web application using JavaScript. And finally, the application cache. A standard way to sort all of the different resources that make up your application in a neat little package that's available off line. For more information, I encourage you to look at the HTML 5 specs for all of these technologies.

They are kind of spread out over the WG web site, and the W3C web site right now. But here's the URLs for them. We'd love to hear from you at the Web Kit open source project, both to report bugs, to hear how awesome we are, to try new nightlies, to interact with the community.

And those cool demos that I showed you. The off line calendar that we implemented, and the Web Kit sticky notes demo for some great database code examples. They're up there. And we also expect the checkers demo to be there pretty soon. Vicki Murley is our Safari Technologies Evangelist, if you have any questions she'd be happy to answer them by e-mail.