WWDC2010 Session 512

Transcript

>> Brady Eidson: Good afternoon everyone.
Welcome to session 512, "Using HTML5 Offline Storage."
My name is Brady Eidson.
I'm an Engineer on the Safari and WebKit team.
Today we're going to be talking
about data, all sorts of data,
data that you as web application
developers are all very familiar with.
Things like HTML, JavaScript, and CSS that make up your
web applications, also the media, a lot of the images,
and other UI and artworks that make our
applications feel very modern and very native.
And these are types of data that you developed
and then served your users from a server.
And there's something that you
deliver that make up your application.
Then there's other type of data that
your application creates and relies on.
Things like application state,
windows sizes, window positions.
So when your user returns to the application,
they might want things to look the same.
Then speaking of your users, they have preferences, all
the little knobs and buttons that you give them to tweak
and change the way they use their application.
You know a few other types of things about your users.
You know they're locale, they're
accessibility type settings, some account info,
an e-mail web app for example might have
some e-mail messages an address book.
It might have some sort of social bookmarking
thing and it's getting a little messy.
But it gets a lot messier when we
think about the all the documents
and stuff that your users create
using your web applications.
And it's just getting crazy how
creative a web app can be these days.
It feels a little bit like the Wild West out
there because you have to wrangle all these data
around without some really good supporting technologies.
You've used things like cookies which were designed for
talking to a server but you've crammed a little nuggets
of data into them and it's kind of worked.
And a lot of web developers have turned to plug-ins
to make things work a little bit and
that has its own host of problems.
And this is all keeping the data
local to the browser of course.
And then there's the ultimate solution, package up the data,
shipped it over the cloud, keep it on a server somewhere.
And this makes sense a lot of the time
when you want to sync data to the server.
But sometimes it's just way overblown, overkill.
So we're going to give you a lasso to give you a new
tool to wrangle all this data about in much better ways.
And we're going to do this using open standards
developed by well-respected standard buddies.
You might have heard of this buzz word lately, HTML5.
It's a technology of standards that Apple really believes
in that makes web apps do some pretty cool things.
And one of the great things about HTML5 is every major
browser has announced some amount of support for it
and all these offline data technologies
we're about to talk about are included there.
So Safari specifically, on Mac, on Windows,
and on iOS devices supports everything
we're going to talk about here today.
In addition, to mobile Safari on iOS
devices supporting these technologies,
UIWebView native applications also
support all of these things in iOS 4.
So this is Safari on all sorts of
types of devices, on Macs, on PCs,
and of course the new mobile hotness that runs iOS 4.
And there's something very interesting about
some of these devices, the laptops, the iPads,
iPod touches that they're very portable devices.
Users take them all over the place but they
don't' always have a network connection.
They're not always tethered to the cloud.
So, as web application developers this kind of presents
a problem and some of you might be asking yourself, "OK,
well, so what can I do without the cloud?"
And that's what we're going to learn today.
Today we're going to solve three great-- three
problems that have been plaguing us for a long time.
First, we're going to make our application itself
accessible offline, packaging up all the resources that make
up the application that you author and served to
your users and cut the cloud out of the picture.
Then we're going to talk about a
great way to persist simple data.
This is something that a lot of you have used cookies and
plug-ins for a little nuggets of data and we're just going
to build that right into the browser in a very reliable way.
And then for the more complex data, we're
going to discuss the full on data center
in the browser and we'll get to that at the end.
So first let's start at the beginning.
We have an application.
We need to make it accessible offline.
There's a fantastic new standard called the
HTML5 application cache and it does that for us.
And it makes the entire application accessible offline.
All the HTML and JavaScript, CSS, all
of the media that makes up the UI.
And even though cache is in the name of the
spec don't conflate it with the HTTP cache.
This is a real persistent, reliable
offline store of your application.
The browser will remember everything
and serve things locally
and it won't ever forget it until someone tells it to.
The spec also provides for automated
updates of your application.
You author the content, put it up on a server,
and then the browser handles getting new
versions of that application to your users.
All you have to do is specify a
resource manifest to make this work.
A resource manifest is just a text
file with the list of URLs.
Every URL of every resource in your application has
to somehow be accounted for in the manifest file.
And we'll go into a little more
detail in that in a little bit.
And then there's a little new non-mandatory API.
You can completely ignore if you choose but
there're some events and things you can listen to,
to help you developed your application cache website and
perhaps provide a richer user experience if you so choose.
So there're two fabulous advantages
of using the application cache.
One, I said a couple of times, I'm going to say it again,
your app works offline in a persistent reliable way
but something is not quite so obvious when you're using the
application cache and the browsers remembers every resource
that makes up your app, is that of course
your app still works online but much faster.
When the browser can completely ignore the network and
just served local copies of every resource that makes
up your application, things are blazing fast.
It feels a lot more native.
So how does it work?
We're using the application cache.
How is our web application loaded in the browser?
So, your user visits the URL for your web application
and Safari sees that you've specified a manifest file.
It already has a copy of all the resources and the manifest.
And it just loads the local copies of the
resources completely ignores the server.
So your user is already using your application and
Safari now in the background without any action from you
or your user change the server says,
"Hey, is there any a new manifest file?
Is there a new update for this application?"
And then they'll compare any new manifest the
server passes back to the manifest that has already.
And if they are different by one byte, they must be
different files, each individual resource is revalidated,
all the HTML, JavaScript, CSS media et cetera.
And then the next time your user visits the URL
for your web application they will be using
the new version of it and that's all automatic.
So to show you a demo of how we put a
manifest in and make something work offline,
I'm going to show you a really cool HTM5
game that a developer out there has made
and it really is one of the greatest games of our time.
It's pretty cool.
I'm sure a lot of you will be very familiar with it.
And I'm a big fan T-Spin.
I'm sure you all heard of T-Spin.
Of course this is T-Spin.
This is a very professional reaching app.
It really speaks to the real T-Spin fan because it fetches
that when the next televised professional T-Spin match is.
It fetches that from a server of T-Spin
resources and it lets me know while I'm playing.
So this is really cool.
This is all pure native web technology.
HTML5 standards and it's the same
T-Spin you all know and love.
But there's a problem with this app and I'm viewing
this from a server and all the time like I take my iPad
to the park for example and there's no Wi-Fi there
and I just want to play some T-Spin out in nature
and have the squirrels watch me play and I can't.
So the application cache is designed to solve this problem.
So let's go ahead and see if we can make this
better and work offline using the application cache.
So I've already gone ahead and made
a manifest file for T-Spin here.
And this is the list of all the
URLs that make up the application.
The manifest file has to start with the phrase cache
manifest that both the spec and the browser vendors
who participate in writing the spec want to make
it very strict and explicit that you are opting
in to this application cache manifest because
it's changing the loading model of web pages.
So one of the explicit things you have to do is
start off your manifest file with cache manifest.
The other thing which I'm not going to show you, I've
already done on this server, is reconfigure my web server
to serve the manifest file with
the text/cache-manifest mime type.
It's a specific mime type that will be in the slides later.
And those two things together tell the web browser, "Hey,
this is a savvy web developer using this cool new stuff
and I'm going to start showing their app offline."
So these are all the resources that are critical to make
T-Spin work offline, a lot of JavaScript, a lot of images.
And then down here, we have a section
called the network section.
Now, this is interesting because sometimes
resources don't make sense to be cached offline.
This is the thing like the live feed that tells
me when the next televised match of T-Spin is.
It only ever makes sense to be
getting that from the network.
So to allow the browser to fetch that URL from
the network, I need to list it in the manifest.
So I've gone ahead and done that here.
So then there's on one more change we have to
do to make application cache work with T-Spin.
We have to edit our main HTML file and we
have to go ahead and specify the manifest.
And now the next time the browser fetches this
HTML, it's going to see there's a manifest.
It's going to fetch the manifest file and start
turning on the application cache for the application.
So now we've done this.
I want to go ahead and use my iPad in the
park and have the squirrels watch me play.
So I'm going to go ahead and demo this on the iPad.
Let me go ahead and load Safari here.
I'm going to ahead and visit T-Spin.
So this is a normal situation.
Wi-Fi is a little fuzzy around here.
It's having to download all of these resources
like any web application normally does.
It's taking a little longer than it was earlier.
OK, here we go.
So this web-- this developer who made this awesome game gave
us an iPad formatted control pad here so that's pretty cool.
This is still taking a lot longer than we planned but
it's still progressing and in about 5 seconds I'm going
to fall back and show this to you on
desktop Safari, four, three, two, one, OK.
Let's just go ahead and show this to you on the desktop.
OK, so I'm going to go ahead and bring
up the T-Spin app here in Safari.
So remember, I've enabled the application cache here.
So eventually, I'm going to prove
to you that this does work offline.
But everything works exactly the same as
it use to before and it's pretty cool.
We're loading the next match.
And actually, that's not what I was expecting to happen.
I think I see here the iPad has finished
loading so I'm going to back to that.
OK.
Meanfest, that's exactly what is happening.
Thanks for calling that up.
And that's why we usually drag and drop code instead
of typing it live because that type of thing happens.
OK. So I'm just going to stick with the desktop here.
So let's go ahead and refresh and see work on the desktop.
This is a little debugging aid I've patched in to
those events I described that are non-mandatory.
They're optional.
And it helps me determine the application--
application cache is actually working.
So I'm going to go ahead and start playing it.
And it's working pretty great,
except something weird happened.
It couldn't find the schedule for the next televised match.
So I bet there's probably a problem with the
manifest file that caused that to happened.
So I'm going to ahead and quit Safari
and take a look at my manifest.
And down here, so this was the URL for that live feed.
As I've mentioned a couple of times, every
URL that our application accesses have
to be accounted for in the manifest file somehow.
And this includes the URLs that come from
the network that we aren't caching offline.
I probably have a typo in here.
In fact, I'm almost sure I do.
So I'm going to go ahead and do something you can only do
in the network section and just replace it with an asterisk.
This is telling the application cache mechanism,
"Hey, this application uses a lot of online content.
I just want to allow it to access the web at will."
So I'm going to go ahead and save my manifest file
and go back to Safari and load my game, there again.
So right now, I'm viewing version 1 of the application.
The version I showed you not 20 seconds ago.
But Safari in the background has gone ahead and
refetched the manifest and revalidated all the resources.
So actually, you can see that there's a missing
image here because that was another part
that I forgot to specify, resources, refresh.
Yeah, I think that it was.
So let's quit Safari one more time.
Watch Safari one more time, OK.
So now we're on version 3 of the application.
My script only called for two versions and there we go.
It has refetched the manifest, updated itself
said, "OK, that little refresh spinning.
I can go ahead and cache that so now it's the displayable."
And now that it's allowed any fetch any URL from the network
it's gone ahead and got my next televised match up there.
So now, this is locally cache in the
browser and it will work offline.
So to prove that to you here on the desktop,
I'm going to-- just to prove this to you.
This is on the different display.
I'm going to go ahead and turn off web sharing.
So the web server is now completely disabled.
I'm going to go ahead and go back to
Safari and load it and it works just fined.
You can see my little red debug indicator here.
It says, "Hey, I tried to fine the manifest file but
I can't because the web server isn't there anymore."
So this actually would be working on the
iPad just great with the Wi-Fi disabled.
It would work out in the park with the squirrels
watching me play and that would be pretty cool.
So, I can play T-Spin, one of the most
exciting games of our time anywhere.
[ Applause ]
So the demo is a little rocky, but we did
cover all the points I wanted to cover.
One of which I only mentioned, didn't show you.
You do have to change your server to specify,
to serve the file with the correct mime type.
Then after you have text file, your list of
your URLs you have to go ahead and specify
that in your HTML using the manifest
attribute on the HTML tag.
Now we did proved to you that resources
not in the manifest due fail to load.
That little progress spinning down there in the corner
and the live feed of the next televised T-Spin match
so I can watch the professionals and really tune my game.
Now when I made a change in the manifest file on
the server side and then refresh that in Safari
that is what triggers an update of the application.
So even if you change a resource
like an HTML or JavaScript file,
you do have to go to the manifest file
and change something to force an update.
You can use a comment to do that.
And that update process, it is automatic.
It's in the background.
Safari does it just by the mere
act of the user visiting the URL.
You don't need to worry about it.
Your user doesn't need to worry about it.
It usually just works.
So that's the application cache, a way
to store the entire application offline.
Now some of you web developers are murmuring,
I can hear some murmurs saying, "Well,
that's great now my app works offline
but what about all the data it creates?
All that data we discuss earlier?"
There're a couple of solutions for that.
First, we'll talk about how to persist
simple data, the little nuggets of data
that many web developers are used
to using cookies and plug-ins for.
And there's a great standard in HTML5 web storage
standard which is designed to do just that.
Now on the web storage spec describes a
standard interface for storing items of data.
And these items of data are simply key/value pairs of data.
If you're familiar with cookies which is a key
string and a value string, exact same type of thing.
If you're familiar with Flash's local storage,
exact same type of thing, key/value pairs of data.
It has origin-based security.
This is the standard security model in the web.
It has been for some time.
And recent HTML5 standards have really solidified it.
This means that a page served from a domain you control
has access to its own set of data and only pages served
from the domain you control have access to that
set of data and pages from other domains do not.
So you and your apps own your data.
Now, there's various implementation of this interface.
This simple interface which I'll show you in a moment,
if you already know how to program in JavaScript,
you already know how to use this interface.
There're various implementations of it.
Concrete objects that have the same programming
model but give you a few different abilities.
What implementations am I talking about?
The spec itself describes one called SessionStorage.
SessionStorage allows different browser tabs or windows
to keep completely separate sessions from each other.
So they each have a data store that only
that browser tab or window can get to.
If some of you who've tried to use cookies
for session management and have noticed
that your application can't be used twice and
at the same time, that's the type of problem
that this is intended to resolve-- to solve.
But the much more immediate one is the LocalStorage.
LocalStorage is a global object that all browser tabs
and windows can get at and it's for persistent data.
If you set an item of data on the LocalStorage object
it is saved to the user's hard drive within the browser
and it will stay there persistently and reliably and it
will be there, a day, a week, a month a year from now.
So those are both in the spec. If some of you
started looking at developing Safari extensions,
the Settings and SecureSettings objects in Safari
extensions implement the exact same interface.
So it really is just a simple JavaScript
programming model, the exact same interface
that works for a lot of different situations.
So exactly how does it work?
I think a common thing is probably your user has a session
of using your application and then they're going to quit.
So we need to save some information about
their session so we can restore it later.
So we can do that with LocalStorage and SessionStorage.
Here for example, we're remembering the
window location, the coordinate on the screen
where the window was-- when the user quit.
The way we remember that is by setting the
windowLocation property on the LocalStorage object.
It's that simple.
This is JavaScript programming.
You're setting a property on an object except the
LocalStorage object has a very unique semantic about it
which means the properties persist to
disk and they're going to be there later.
So this is something that a user could quit the browser
and come back a week later and fire up your web app again
and the window location property will
be there on the LocalStorage object.
So that works for properties, you know the name
of beforehand with the dot property notation.
You can use the array, bracket property, access notation
in JavaScript if you want for more variable properties.
These are just JavaScript objects that are
like collections you can iterate over them.
So for example, I want to iterate
over all of the data items stored
in the sessionStorage because we're saving the session out.
So I can just go forth and in sessionStorage.
Then for each item, I'm just going to go ahead and move
it from sessionStorage to localStorage to save it off.
And there's another API, an actual method call on these
storage objects that you can use called setItem to do that.
And course, there's a removeItem for removing
individual items from a storage object
and you can just wipe the whole
thing out at once if you chose.
So to show you a demo of how easy it is to
spice up an already existing app using a little
of this LocalStorage magic, I'd like to invite
one of the finest T-Spin players I know,
up on stage my fellow colleague, Andy Estes,
up on the stage to show you how that works.
[ Applause ]
>>Andy Estes: So, Brady showed us this really
great demo of how we can take our web application
to make it available offline using
the application cache and, you know,
the example he use was this really fun game called T-Spin.
I've been really enjoying playing this.
A childhood favorite game of mine and, you know, now that
it's implemented using these great HTML5 web technologies,
I've really been having a lot of fun playing it.
And to be honest, you know, things have been
getting pretty competitive in the office.
Brady and I are really always kind of jousting
to see who can get top score in this game.
So, you know, one of the nice things that the
developer provided for us here is tracking the score.
So you can see that as I played through
here, right over here it's updating my score.
And, you know, even better, it's tracking my high score.
So, you know, Brady and I can play separate
matches and we can see who gets the highest score.
Now the really nice thing about this
high score is that it's persistent.
So if I were to go and, you know, quit out
Safari and then decide to come back in later,
I can simply go back to the game and
sure enough my high score is remembered.
So this is really interesting, let's take a look at the code
and see how the developer chose to
implement this high score tracking.
So I'm going to leave Safari and go over to Xcode.
And I happened to have access to the
JavaScript of this game of course.
So there is an object in this game called
"High Score" and this object has a constructor.
So when the game starts up this constructor is called
and it's initializing a property called "High Score"
and it's calling its helper function
called retrieveHighScore.
Now presumably, retrieveHighScore is reaching
out into some sort of persistent data store,
where the browser can access and
seeing if a high score is there.
And if so it's pulling it in and
setting this property to that value.
And if for whatever reason we get a null
we'll just initialize high score to zero.
So, then as we go and play the game,
we have additional properties or--
I'm sorry, we have some additional methods on this
object that, you know, each time the score is updated,
what its going to do is it's going to check to
see if that score is higher than the high score
and if it is it will first, you know, set the property
to that new value and then also call storeHighScore.
So storeHighScore is another helper
function like retrieveHighScore.
It's going to go and somehow save this
value off into persistent storage.
So why don't we go and see what
retrieve and storeHighScore are doing.
Let's switch over another file here.
And we see that retrieveHighScore is
calling a function called readCookie,
and storeHighScore is calling a
function called createCookies.
So, ah-ha, we're using cookies.
And Brady covered cookies a little bit.
You know, cookies obviously work.
This game works fine with cookies
but there're a couple disadvantages.
And you know, the first disadvantage is
that it's really kind of the wrong idiom.
Cookies are designed to transmit data between user agents
and servers but we just saw with the application cache
that this application works just fine
offline without any access to a server.
So, you know, a cookie isn't really
appropriate in this case.
And secondly, you know, if we dig in to
the implementation of these two functions,
we'll see that they're actually pretty complicated.
You know, I have to build this particularly
formatted string and set it equal to document.cookie.
It has to have the key/value pair.
It needs to have an expiration date and
a path to send it back to the server.
You know, I care about the key/value pair,
but I don't really care when it expires
or what path that sent to him on the server.
But I have to provide these details,
otherwise, things just wont' work.
And you know, if we look in the read
cookie, things are equally complicated.
You know, I get the string back from document.cookie
that has all the cookies for this domain, you know,
I have to tokenize it based on a semi-colon.
I have to loop through and try to find my key.
I have to worry about if there's
any white space and trim that out.
And then finally, and I'll return the substring
that represents the value for that key.
So this is really complicated.
And what I'm trying to do is something really simple.
I'm trying to just persist and
retrieve a simple key/value pair.
Luckily, LocalStorage provides a really
simple way for us to do this effectively.
So, let's look at what these routines
would like with LocalStorage.
So I'll delete this version.
And if I can find where my second screen is
I'll bring over the LocalStorage version.
And, you know, wow, this is a lot simpler.
It's the same two functions, retrieveHighScore
and storeHighScore.
But they're one line functions.
I went from maybe 40 lines of JavaScript
down to 2 one line functions.
As Brady mentioned, you know, I'm just using
the JavaScript's programming techniques that you
as developers are all quite familiar with.
I have a LocalStorage object.
I'm reading a property called High Score of that object.
You can either use the dot property notation.
You can use the array access notation like I did down here.
You can use them interchangeably and
either one of them will just work.
So we can say that this, you know-- this kind
of code matches the complexity of the problem.
It's a simple problem and we can
use simple code to solve it.
But it would be nice if this actually still works.
So let's say that-- and let's go back into T-Spin
and see if I can actually still play the game.
And sure enough I can.
So my high score is reset because
I'm not using my cookies anymore.
I'm using a local storage property.
But we can see it's updating as I'm
playing and even better I can quit Safari,
I can come back in and yeah, it maintained my high score.
So that's very cool.
[Applause] Thanks.
[Applause] Another really cool thing about
using LocalStorage instead of cookies is
that I can use some features of the Web
Inspector to get a little more information.
So I'm going to pop-up the Web Inspector.
Across the top, I have this tab called storage.
And now that I've set a LocalStorage or-- yeah, a
local storage property, there's now this new item
in this left-hand column called Local Storage.
And if I clicked on it, sure enough I see my key/value pair
that I set in code and I can inspect its current value.
And you know, even better what I can do, like I said Brady
and I been really competitive,
I'm really trying to beat him.
So, let's see.
[ Pause ]
Yeah, I don't think he's going to be able to
beat that one but don't tell him I did that.
Well, alright, back to you Brady.
[ Applause ]
>>Brady Eidson: OK.
Thanks Andy.
So I stepped out for a minute I didn't
see anything he might have done.
He did OK right guys?
Great. OK, so simple programming techniques, simple demo.
And that's just fantastic.
And that's the thing is it really just a
straightforward if you know how to program a JavaScript.
What Andy showed is that you can use the LocalStorage
object to globally and persistent store data.
You can quit the browser, relaunch, the data is
still there and it will be there for the future.
And he also demonstrated, you know, no matter
how you reference the property and his case,
I believe those high score using the dot
property, access the array bracket notation.
Or if you wanted to use the getItem
call that is in the LocalStorage API.
It's all the same property and you
can just choose how you want to code.
So that was web storage, simple stuff,
simple data, simple straightforward solution.
But now I hear some more murmurs in the audience
from some advance web developer saying
"OK, I can store the simple stuff.
But I need something with a little more oomph.
I've got megabytes of data that I'm wrangling around and
it's got structure and it's all this relational data"
and well that's what the data center
and the browser is about.
And by the data center and browser I'm talking
about the HTML5 SQL databases spec. The
SQL databases spec is about real-world SQL.
This is the same structured query language that many
of you are familiar with form working on servers,
working on infrastructure or from
taking databases classes and college.
But it's the real-world SQL.
We're moving on around large amounts of data and
it might take some time to process on that data.
So the API is asynchronous and it is callback-based.
Safari will handle all this stuff on a background thread
and the way you interact with the database mechanism is
by providing some JavaScript callback functions
to take care of things when you need to.
Again, like session storage and local storage,
it has the same origin base security model
that is this standard security model of the web.
Pages served from your domain that you own and control
but the only ones who can get at your set of databases.
So there are some advantages of keeping
it local, keeping databases local.
One is of course the theme of the talk it works offline.
This is a database that is not on some server
that we need to go through the cloud to get to.
This is a database accessible on
our users' machines in the browser.
So this is great in some situations.
But I know a lot of you are thinking, "Well, I have this
complex structure relational data that I need to store it
on the serve-- store it on a server somewhere.
The whole point of my application or my
set up is that I sync this data to a server
and then I sync it back down to the browser later."
Well, you can still use the local database
to cache that data locally and to prepare
for the eventuality where there is no network connection.
And when you do so, you get fantastic benefits
along the lines of better performance.
When the database is being created locally, fetching
results from the rows and tables is just instantaneous.
And then lower latency, we're cutting the network out of
the situation, we don't have to travel across the world,
we don't have to travel through the
airways and Wi-Fi or cellular connections,
we just have to travel through
our machine to the user's disc.
So things are really quick.
And then especially in this portable
devices when we're disabling the radios
and we're not using this power-hungry broadcast to get
at this data because we have a locally cache copy of it,
we can improve battery life by quite a bit.
Radios are very expensive for batteries.
So I'm going to focus on one thing back
on the overview slide really quick.
And that is, real-world SQL.
What do I mean when I say real-world SQL?
I absolutely mean everything you think it means.
I mean there's tables of data that you can
create and drop at will and there's rows
of data you can throw massive amounts of rows at the
database and it will handle them and chew them up
and I'm sure there's indexes when
you know the scheme of your database,
you can provide performance hints to make it work faster.
There're definitely triggers you can install so you can
make things work and stay consistent as data is dropped
and stuff, and you bet there's transactions.
Their built into the API.
We don't let you forget them.
They're so important to performance and consistency that
they're the very fundamental construct of the database API.
So how does this API work?
I'll walk you through it.
Since it's asynchronous, it takes a
little bit of walking through the trails.
So let's follow the bread crumbs.
First, you get a database object to work with.
There's a new call on the window object called openDatabase.
It takes a few arguments.
The only really important one is that
first argument the database identifier.
In this case, we're referring to
the base called "MyDatabase."
And that's the unique identifier for the database.
If I open the same database again in the future, I'll
be getting an access to the same data stored in it.
So when do that openDatabase returns you a database object?
There're a couple things you can do with it.
But by far, the most important
one is start a SQLTransaction.
And the way you do that is by calling
transaction on the database object.
There're a few different flavors of this method but the one
that lets you actually do something useful is
the one that takes a single callback function.
So starting this transaction, it's going
to happen on this background thread,
Safari's going to handle all the heavy lifting.
And then when the transaction is open and ready to go,
that's when your callback function is going to be called.
Your callback function is going to take a single
argument which is an SQLTransaction object.
And this object is where things happen, where SQL is run.
So using this object we can execute
some SQL by calling executeSql.
And this is just a very simple SQL statement.
I'm creating a test table with the test value in it.
But this is where my database experience
and from JavaScript in the browser begins.
So let's go into a little more depth by showing you a demo.
OK, so if any of you have researched the SQL database
spec, Google around for it, one thing you might have run
across is what has become the canonical example of a web
database app that we put together when we first implemented.
And that is of course the WebKit Sticky Notes.
What better thing to store in a
relational database than some sticky notes.
So that's what we use as our demo.
So we see here I got the sticky note I can drag around.
I can put some stuff on it.
I'm on stage mom.
So she can see that later and its
storing this in the database.
Now I can go ahead and quit Safari, relaunch
it, go ahead and go back to the same page
and have the exact same note there as the same
contents and there's actually a lot more data going
on in this note behind the scenes
that you might not be aware of.
First off, it's got the text of course which-- there we go.
But down here, it also has the last modified date.
As I move it around, it remembers
the position of the sticky note.
And then of course, I might want multiple
notes and you'll notice that their stacked,
they have a Z order that shifts
around as I select a new note.
So we also remember the Z order.
So take a quick mental snapshot
here of how these notes look.
I'm going to go ahead and quit Safari, relaunch it, go back
to this page and all of that information, the locations
and the Z orders relations between
them is stored in the database.
So it's pretty cool.
Let's go ahead and bring up the Web Inspector.
As Andy showed you earlier, it can
introspect into local storage pretty well
but it also has a great way to look at the databases.
So I'm guessing by looking at the Web
Inspector here, we called our database Note Test
because that's what shows up in the sidebar here.
And the inside of Note Test is a
table called "WebKit Sticky Notes."
And indeed, these are all the notes that I have on here.
It's got the idea of the note, the text of the note,
the time stamp, their locations, their Z order.
So that's all in the database here.
I can even like I have a little command prompt
here so I can do some stuff in the database
if I want, it has tab completion, helps out.
So the Web Inspector is a great tool to help
you use database in your web application.
So right now we're looking at the sticky notes that
are hosted at webkit.org but I have a local copy
on my laptop because I use these all the time.
I use these to organize my life because I have a
lot of stuff going on and I just need a little help.
So I'm going to ahead and bring up my local copy.
Don't try to pry into my personal life too much but
this is the type of stuff that's on my plate right now.
All the types of things I have to worry about.
But what is really different about my local copy is
that I got it a search box up here because I have
so many sticky notes flying around, it's hard to keep
track of everything that's going on in my life sometimes.
So I know I need to search for things
like I know I need to go shopping
after the WWDC party tonight so
I have a shopping list in here.
I can go ahead and type a search query, OK.
So I just-- "sh" was good enough
so I can see my shopping list.
This is all just standard web technology
here and it made everything I didn't--
I wasn't interested in go away
and I brought up my shopping list.
And as you know it by now I'm obsessed with
T-spin lately especially with beating Andy
because somehow he keeps on putting up amazing scores.
So I have a lot of notes about T-spin.
I had noticed on my shopping list, I have to buy a
strategy guide, I need to make sure to watch that match
on TV tomorrow and so that's what
I have to do regarding T-spin.
So the search box, this really changed my life.
It made using this so much easier.
So let's go ahead and see how I implemented that.
Since all these are in a database, all
I had to do was write a little SQL magic
and a little JavaScript to query the database for matches.
So you can see here at the beginning
of my method I do a little validation
to make sure I'm only performing one search at once
and to make sure I reset everything
to basic if there is no search query.
But then right here, the db.transaction
this is where the magic starts happening.
So right here I'm calling transaction
on the database object like I showed you
on slides and I'm providing my callback function.
It could be a function I wrote somewhere
else in my code but I went ahead
and declared the function inline
here, isn't JavaScript great?
So in my callback function I get a transaction object.
So I go ahead and take that transaction
object and execute some SQL.
Let me make the window a little
bigger here and executes some SQLs.
So this one SQL statement is leveraging the power of
the database to look at all the text of all the notes
and give me the matches of all
the notes that I'm searching for.
So when I execute that statement, this is a different
form of the function call I didn't show you in the slides.
I provide a callback to get the results out of the database
because of course it's useless
if we can't get the results out.
So in this callback, I'm getting a results object.
Now the documentation in the spec and
in this Sticky Notes example code,
you can see what the results of the object is like.
Basically, I get rows of results here.
I can just go ahead and iterate over those rows and look
for the property I'm interested in, here it's the ID,
and then I have those note objects live, I've
already created them from the database already
when I first visited the web app so I can
go ahead and change some classes on them
to pop the matches out and make the non-matches go away.
So you know about 20 lines of JavaScript one SQL
statement leveraging the power of the database
to add a really cool feature to what was
already kind of a pretty cool little demo.
So that's the WebKit Sticky Notes.
[ Applause ]
So as I showed you, SQL queries
available directly from JavaScript.
This is a SQL database and web technology meshed
together and we can do some pretty cool stuff with it
and I think you can do some pretty cool stuff with it too.
We can handle complex relational data in the browser, these
sticky notes have enough little nuggets of data about them
that trying to store them in local storage or cookies
or in a plug-in or wrapping them up and shipping it off
to a server just to fetch them again
later, probably be a little bit of a pain.
So we can store that relation and that
structure locally in the browser from JavaScript.
And what I didn't actually show you
in the demo, but what I've alluded to
and I think you can imagine is definitely true.
When it makes sense to cache this
data or store it locally offline
in our users' machines we get performance
superior to the cloud.
Things-- modern machines are just so fast that handling
the database for one user, piece of cake, no sweat.
And we can ignore the network, the latency and work even
when there isn't a network, then that's pretty great.
So that's everything I had to talk to you about today.
We covered the application cache a standard way to store
the resources that make up your application offline
so your users can use your web application
with no network connection at all.
We talked about the web storage spec a way to sort
key/value pairs of data in a persistent and reliable manner.
And then we talked about the data center and the browser.
SQL databases a full relational database
available to your JavaScript to your apps.
So for more info, you're welcome to contact
Vicki Murley, the Safari Technologies Evangelist.
Each of these three technologies, are in three different
specs that make up the HTML5 family of technology.
So here're the URLs for looking up at those.
We'd love to hear form you at the WebKit Open Source Project
especially to check out that WebKit Sticky Notes demo.
And, of course, the Apple Developer Forums
are always available for your needs.