forked from zenorocha/diveintohtml5
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoffline.html
267 lines (191 loc) · 31.6 KB
/
offline.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
<!DOCTYPE html>
<meta charset=utf-8>
<title>Aplicações Web Offline - Dive Into HTML5</title>
<!--[if lt IE 9]><script src=j/html5.js></script><![endif]-->
<link rel=alternate type=application/atom+xml href=https://github.com/diveintomark/diveintohtml5/commits/master.atom>
<link rel=stylesheet href=screen.css>
<style>
body{counter-reset:h1 8}
</style>
<link rel=stylesheet media='only screen and (max-device-width: 480px)' href=mobile.css>
<link rel=prefetch href=index.html>
<p>Você está aqui: <a href=index.html>Home</a> <span class=u>‣</span> <a href=table-of-contents.html#offline>Dive Into <abbr>HTML5</abbr></a> <span class=u>‣</span>
<h1><br>Vamos Tornar Isso Offline</h1>
<p id=toc>
<p class=a>❧
<h2 id=divingin>Mergulhando</h2>
<p class=f><img src=i/aoc-w.png alt=O width=110 height=108>que são aplicações web offline? Em um primeiro momento, parece uma contradição de termos. Páginas da web são coisas que você faz download e renderiza. Download implica conexão com a rede. Como você pode fazer download quando você está offline? É claro, você não pode. Mas você <em>pode</em> fazer download quando você está online. E é assim que as aplicacões offline da <abbr>HTML5</abbr> funcionam.
<p>De forma simples, uma aplicacão web offline é uma lista de <abbr>URL</abbr>s — <abbr>HTML</abbr>, <abbr>CSS</abbr>, JavaScript, imagens, ou qualquer tipo de recurso. A página inicial de uma aplicação web offline aponta para essa lista, chamado de arquivo manifesto, que é apenas um arquivo texto localizado em qualquer lugar no servidor web. Um navegador web que implementa aplicações offline em <abbr>HTML5</abbr> irá ler a lista de <abbr>URL</abbr>s do arquivo manifesto, fazer download dos recursos, realizar o cache deles localmente, e automaticamente manter os arquivos locais atualizados à medida que são alterados. Quando chegar a hora em que você tentar acessar as aplicações web sem uma conexão de rede, seu navegador web irá automaticamente apontar para as cópias locais.
<p>A partir disso, a maioria do trabalho está com você, desenvolvedor web. Existe uma indicação no <abbr>DOM</abbr> que irá dizer se você está online ou offline. Existem eventos que são disparados quando seu status offline muda (em um minuto você está offline e no próximo minuto está online, ou vice-versa). Mas é basicamento isso. Se a sua aplicação cria dados ou salvo estados, está com você a missão de <a href=storage.html>armazenar dados localmente</a> enquanto está offline e sincronizar isso com o servidor remoto uma vez estando online novamente. Em outras palavras, <abbr>HTML5</abbr> pode levar suas aplicações web offline. O que você faz quando chegar lá é com você.
<table class=bc>
<caption>Suporte offline</caption>
<thead>
<tr><th title="Internet Explorer">IE<th title="Mozilla Firefox">Firefox<th title="Apple Safari">Safari<th title="Google Chrome">Chrome<th>Opera<th>iPhone<th>Android
<tbody>
<tr><td>·<td>3.5+<td>4.0+<td>5.0+<td>10.6+<td>2.1+<td>2.0+
</table>
<p class=a>❧
<h2 id=manifest>O Manifesto Cache</h2>
<p>Uma aplicação web offline utiliza um arquivo de manifesto cache. O que é um arquivo manifesto? É uma lista de todos os recursos que a sua aplicação web irá precisar acessar quando estiver desconectada de uma rede. Afim de iniciar o processo de download e cache desses recursos, você irá precisar apontar para o arquivo manifesto, utilizando o atributo <code>manifest</code> no seu elemento <code><html></code>.
<pre><code><!DOCTYPE HTML>
<html <mark>manifest="/cache.manifest"</mark>>
<body>
...
</body>
</html></code></pre>
<p>Seu arquivo de manifesto cache pode estar localizado em qualquer lugar do seu servidor web, mas precisa estar servido sob o tipo de conteúdo <code>text/cache-manifest</code>. Se você está rodando um servidor web baseado no Apache, você provavelmente precisa adicionar uma <a href=http://httpd.apache.org/docs/2.2/mod/mod_mime.html#addtype>diretiva <code>AddType</code></a> no seu arquivo <code>.htaccess</code> na raíz do seu diretório web:
<pre><code>AddType text/cache-manifest .manifest</code></pre>
<p>Depois certifique-se que o nome do seu arquivo de manifesto cache termina com <code>.manifest</code>. Se você usa um servidor web diferente ou uma configuração diferente do Apache, consulte a documentação do seu servidor em controle de cabeçalho <code>Content-Type</code>.
<div class="pf clear">
<h4>Pergunte ao Professor Marcação</h4>
<div class=inner>
<blockquote class=note>
<p><span>☞</span>P: Minha aplicação web abrange mais de uma página. Preciso de um atributo <code>manifest</code> em cada página, ou posso colocar apenas na home page?
<p>R: Cada página da sua aplicação web precisa de um atributo <code>manifest</code> que ponta para o manifesto cache para toda aplicação.
</blockquote>
</div>
</div>
<p>OK, então cada uma das suas páginas <abbr>HTML</abbr> apontam para seu arquivo de manifesto cache, e seu arquivo de manifesto cache sendo servidor com o devido cabeçalho <code>Content-Type</code>. Mas o que acontece <em>dentro</em> do arquivo manifesto? É aqui onde as coisas começam a ficar interessante.
<p>A primeira linha de todo arquivo de manifesto cache é assim:
<pre><code>CACHE MANIFEST</code></pre>
<p>Depois disso, todos os arquivos manifesto são divididos em três partes: a seção “explícita”, a seção “fallback”, e a seção “lista branca online”. Cada seção tem um header, na sua própria linha. Se o arquivo manifesto não tiver nenhum desses cabeçalhos de seção, todos os recursos listados estão implicitamente na seção “explícita”. Tente não se debruçar sobre a terminologia, se não sua cabeça irá explodir.
<p>Aqui está um arquivo manifesto válido. Ele lista três recursos: um arquivo <abbr>CSS</abbr>, um arquivo JavaScript, e uma imagem <abbr>JPEG</abbr>.
<pre><code>CACHE MANIFEST
/clock.css
/clock.js
/clock-face.jpg</code></pre>
<p>Esse arquivo de manifesto cache não possui cabeçalhos de seção, então todos os recursos listados estão na seção “explícita” por padrão. Recursos na seção “explícita” serão feitos download e cache localmente, e serão usados no lugar de seus respectivos semelhantes sempre que você estiver descontectado de uma rede. Assim que for carregamento esse arquivo de manifesto cache, seu navegador irá realizar o download de <code>clock.css</code>, <code>clock.js</code>, e <code>clock-face.jpg</code> do diretório raíz do seu servidor web. Então você pode desplugar seu cabo de rede e atualizar a página, e todos aqueles recursos estarão disponíveis offline.
<div class="pf clear">
<h4>Pergunte ao Professor Marcação</h4>
<div class=inner>
<blockquote class=note>
<p><span>☞</span>P: Preciso listar minhas páginas <abbr>HTML</abbr> no meu manifesto cache?<br>
R: Sim e não. Se a sua aplicação web inteira está contida em uma única página, apenas certifique-se que a página aponta para o manifesto cache usando o atributo <code>manifest</code>. Quando você navega em uma página <abbr>HTML</abbr> com o atributo <code>manifest</code>, a página em si assume ser parte da aplicação web, então você não precisa listá-la no arquivo manifesto. Entretanto, se a sua aplicação web agrega múltiplas páginas, você deve listar todas as páginas <abbr>HTML</abbr> no arquivo manifesto, caso contrário o navegador não saberá que existem outras páginas <abbr>HTML</abbr> que precisam fazer download e cache.
</blockquote>
</div>
</div>
<h3 id=network>Seções de Rede</h3>
<p>Aqui está um exemplo um pouquinho mais complicado. Suponha que você queira que sua aplicação relógio rastreie os visitantes, usando um script <abbr>tracking.cgi</abbr> que é carregado dinâmicamente por um atributo <code><img src></code>. Realizando o cache desse recurso irá acabar com o propósito desse rastreamento, então esse recurso nunca deve realizar cache e nunca deve estar disponível offline. Aqui está o que você deve fazer:
<pre><code>CACHE MANIFEST
<mark>NETWORK:
/tracking.cgi</mark>
CACHE:
/clock.css
/clock.js
/clock-face.jpg</code></pre>
<p>Esse arquivo de manifesto cache inclui cabeçalhos de seção. A linha marcada com <code>NETWORK:</code> é o começo dessa seção “lista branca online”. Recursos nessa seção nunca sofrerão cache e não estarão disponíveis offline. (Tentar carregá-los enquanto estiver offline irá resultar em um erro.) A linha marcada com <code>CACHE:</code> é o começo da seção “explícita”. O resto do arquivo de manifesto cache é o mesmo do exemplo anterior. Cada um dos três recursos listados estará em cache e disponível offline.
<h3 id=fallback>Seções de Fallback</h3>
<p>Esse é mais um tipo de seção em um arquivo de manifesto cache: a seção fallback. Na seção fallback, você pode definir substituições para recursos online que, por uma razão qualquer, não devem realizar cache ou não realizaram cache com sucesso. A especificação da <abbr>HTML5</abbr> oferece esse exemplo usando a seção fallback:
<pre><code>CACHE MANIFEST
FALLBACK:
/ /offline.html
NETWORK:
*</code></pre>
<p>O que isso faz? Primeiro, considere um site que contém milhões de páginas, como no <a href=http://pt.wikipedia.org/wiki/Main_Page>Wikipedia</a>. Você não poderia fazer download do site inteiro, nem você iria querer. Mas suponha que você consiga deixar <em>parte</em> disso disponível offline. Como você iria decidir quais página fazer cache? Que tal isso: cada página que você já tenha visto em uma hipotética Wikipedia offline seriam feitos download e cache. Isso incluiria cada entrada da enciclopédia que você já visitou, cada página de discussão (onde você encontra discussões improvisadas sobre uma entrada particular da enciclopédia), e cada página de edição (onde você consegue, de fato, realizar alterações sobre uma entrada particular).
<p>É isso que o manifesto cache faz. Suponha que cada página <abbr>HTML</abbr> (entrada, discussão, edição, histórico) no Wikipedia apontasse para esse arquivo de manifesto cache. Quando você visita qualquer página que aponta para o manifesto cache, seu navegador diz your browser says “ei, essa página é parte de uma aplicação web offline, essa é alguma que eu conheço?” Se o seu navegador nunca fez download desse arquivo de manifesto cache, ele irá definir um novo “appcache” offline; (curto para “aplicação cache”), fazer download de todos os recursos listados no manifesto cache, e depois adicionar a página corrente para o appcache. Se o seu navegador conhece o manifesto cache, irá simplesmente adicionar a págona corrente para o appcache existente. Dessa forma, a página que você acabou de visitar acaba no appcache. Isso é importante. Significa que você pode ter uma aplicação web offline que, de forma “preguiçosa”, adiciona páginas à medida que as visita. Você não precisa listar cada uma das suas páginas <abbr>HTML</abbr> no seu manifesto cache.
<p>Agora veja a seção fallback. A seção fallback nesse manifesto cache tem apenas uma única linha. A primeira parte da linha (antes do espaço) não é uma <abbr>URL</abbr>. É na verdade um padrão de <abbr>URL</abbr>. O único caractere (<code>/</code>) irá definir qualquer página do seu site, não apenas a página de entrada. Quando você tentar visitar a página enquanto estiver offline, seu navegador irá procurar por ele no appcache. Se o seu navegador encontra a página no appcache (porque você a visitou enquanto esteve online, e a página foi adicionada de forma implícita no appcache naquela hora), então seu navegador irá exibir uma cópia da página em cache. Se o seu navegador não encontrar a página no appcache, ao invés de exibir uma mensagem de erro, irá exibir a página <code>/offline.html</code>, como especificado na segunda parte daquela linha na seção fallback.
<p>Finally, let’s examine the network section. The network section in this cache manifest also has just a single line, a line that contains just a single character (<code>*</code>). This character has special meaning in a network section. It’s called the “online whitelist wildcard flag.” That’s a fancy way of saying that anything that isn’t in the appcache can still be downloaded from the original web address, as long as you have an internet connection. This is important for an “open-ended” offline web application. It means that, while you’re browsing this hypothetical offline-enabled Wikipedia <em>online</em>, your browser will fetch images and videos and other embedded resources normally, even if they are on a different domain. (This is common in large websites, even if they aren’t part of an offline web application. <abbr>HTML</abbr> pages are generated and served locally, while images and videos are served from a <a href=http://en.wikipedia.org/wiki/Content_delivery_network><abbr title="content delivery network">CDN</abbr></a> on another domain.) Without this wildcard flag, our hypothetical offline-enabled Wikipedia would behave strangely when you were online — specifically, it wouldn’t load any externally-hosted images or videos!
<p>Is this example complete? No. Wikipedia is more than <abbr>HTML</abbr> files. It uses common <abbr>CSS</abbr>, JavaScript, and images on each page. Each of these resources would need to be listed explicitly in the <code>CACHE:</code> section of the manifest file, in order for pages to display and behave properly offline. But the point of the fallback section is that you can have an “open-ended” offline web application that extends beyond the resources you’ve listed explicitly in the manifest file.
<p class=a>❧
<h2 id=events>The Flow of Events</h2>
<p>So far, I’ve talked about offline web applications, the cache manifest, and the offline application cache (“appcache”) in vague, semi-magical terms. Things are downloaded, browsers make decisions, and everything Just Works. You know better than that, right? I mean, this is web development we’re talking about. Nothing ever Just Works.
<p>First, let’s talk about the flow of events. Specifically, <abbr>DOM</abbr> events. When your browser visits a page that points to a cache manifest, it fires off a series of events on the <code>window.applicationCache</code> object. I know this looks complicated, but trust me, this is the simplest version I could come up with that didn’t leave out important information.
<ol>
<li>As soon as it notices a <code>manifest</code> attribute on the <code><html></code> element, your browser fires a <strong><code>checking</code></strong> event. (All the events listed here are fired on the <code>window.applicationCache</code> object.) The <code>checking</code> event is always fired, regardless of whether you have previously visited this page or any other page that points to the same cache manifest.
<li>If your browser has never seen this cache manifest before...
<ul>
<li>It will fire a <strong><code>downloading</code></strong> event, then start to download the resources listed in the cache manifest.
<li>While it’s downloading, your browser will periodically fire <strong><code>progress</code></strong> events, which contain information on how many files have been downloaded already and how many files are still queued to be downloaded.
<li>After all resources listed in the cache manifest have been downloaded successfully, the browser fires one final event, <strong><code>cached</code></strong>. This is your signal that the offline web application is fully cached and ready to be used offline. That’s it; you’re done.
</ul>
<li>On the other hand, if you have previously visited this page or any other page that points to the same cache manifest, then your browser already knows about this cache manifest. It may already have some resources in the appcache. It may have the entire working offline web application in the appcache. So now the question is, has the cache manifest changed since the last time your browser checked it?
<ul>
<li>If the answer is no, the cache manifest has not changed, your browser will immediately fire a <strong><code>noupdate</code></strong> event. That’s it; you’re done.
<li>If the answer is yes, the cache manifest <em>has</em> changed, your browser will fire a <strong><code>downloading</code></strong> event and start re-downloading every single resource listed in the cache manifest.
<li>While it’s downloading, your browser will periodically fire <strong><code>progress</code></strong> events, which contain information on how many files have been downloaded already and how many files are still queued to be downloaded.
<li>After all resources listed in the cache manifest have been re-downloaded successfully, the browser fires one final event, <strong><code>updateready</code></strong>. This is your signal that the new version of your offline web application is fully cached and ready to be used offline. <em>The new version is not yet in use.</em> To “hot-swap” to the new version without forcing the user to reload the page, you can manually call the <code>window.applicationCache.swapCache()</code> function.
</ul>
</ol>
<p>If, at any point in this process, something goes horribly wrong, your browser will fire an <strong><code>error</code></strong> event and stop. Here is a hopelessly abbreviated list of things that could go wrong:
<ul>
<li>The cache manifest returned an <abbr>HTTP</abbr> error 404 (Page Not Found) or 410 (Permanently Gone).
<li>The cache manifest was found and hadn’t changed, but the <abbr>HTML</abbr> page that pointed to the manifest failed to download properly.
<li>The cache manifest changed while the update was being run.
<li>The cache manifest was found and had changed, but the browser failed to download one of the resources listed in the cache manifest.
</ul>
<h2 id=debugging>The fine art of debugging, a.k.a. “Kill me! Kill me now!”</h2>
<p>I want to call out two important points here. The first is something you just read, but I bet it didn’t really sink in, so here it is again: if even a single resource listed in your cache manifest file fails to download properly, the entire process of caching your offline web application will fail. Your browser will fire the <code>error</code> event, but there is no indication of what the actual problem was. This can make debugging offline web applications even more frustrating than usual.
<p>The second important point is something that is not, technically speaking, an error, but it will look like a serious browser bug until you realize what’s going on. It has to do with exactly how your browser checks whether a cache manifest file has changed. This is a three-phase process. This is boring but important, so pay attention.
<ol>
<li>Via normal <abbr>HTTP</abbr> semantics, your browser will check whether the cache manifest has expired. Just like any other file being served over <abbr>HTTP</abbr>, your web server will typically include meta-information about the file in the <abbr>HTTP</abbr> response headers. Some of these <abbr>HTTP</abbr> headers (<code>Expires</code> and <code>Cache-Control</code>) tell your browser how it is allowed to cache the file without ever asking the server whether it has changed. This kind of caching has nothing to do with offline web applications. It happens for pretty much every <abbr>HTML</abbr> page, stylesheet, script, image, or other resource on the web.
<li>If the cache manifest has expired (according to its <abbr>HTTP</abbr> headers), then your browser will ask the server whether there is a new version, and if so, the browser will download it. To do this, your browser issues an <abbr>HTTP</abbr> request that includes that last-modified date of the cache manifest, which your web server included in the <abbr>HTTP</abbr> response headers the last time your browser downloaded the manifest file. If the web server determines that the manifest file hasn’t changed since that date, it will simply return a <code>304 (Not Modified)</code> status. Again, none of this is specific to offline web applications. This happens for essentially every kind of resource on the web.
<li>If the web server thinks the manifest file has changed since that date, it will return an <abbr>HTTP</abbr> <code>200 (OK)</code> status code, followed by the contents of the new file, along with new <code>Cache-Control</code> headers and a new last-modified date, so that steps 1 and 2 will work properly the next time. (<abbr>HTTP</abbr> is cool; web servers are always planning for the future. If your web server absolutely must send you a file, it does everything it can to ensure that it doesn’t need to send it twice for no reason.) Once it’s downloaded the new cache manifest file, your browser will check the contents against the copy it downloaded last time. If the contents of the cache manifest file are the same as they were last time, your browser won’t re-download any of the resources listed in the manifest.
</ol>
<p>Any one of these steps can trip you up while you’re developing and testing your offline web application. For example, say you deploy one version of your cache manifest file, then 10 minutes later, you realize you need to add another resource to it. No problem, right? Just add another line and redeploy. Bzzt. Here’s what will happen: you reload the page, your browser notices the <code>manifest</code> attribute, it fires the <code>checking</code> event, and then... nothing. Your browser stubbornly insists that the cache manifest file has not changed. Why? Because, by default, your web server is probably configured to tell browsers to cache static files for a few hours (via <abbr>HTTP</abbr> semantics, using <code>Cache-Control</code> headers). That means your browser will never get past step 1 of that three-phase process. Sure, the web server knows that the file has changed, but your browser never even gets around to asking the web server. Why? Because the last time your browser downloaded the cache manifest, the web server told it to cache the resource for a few hours (via <abbr>HTTP</abbr> semantics, using <code>Cache-Control</code> headers). And now, 10 minutes later, that’s exactly what your browser is doing.
<p>To be clear, this is not a bug, it’s a feature. Everything is working exactly the way it’s supposed to. If web servers didn’t have a way to tell browsers (and intermediate proxies) to cache things, the web would collapse overnight. But that’s no comfort to you after you spend a few hours trying to figure out why your browser won’t notice your updated cache manifest. (And even better, if you wait long enough, it will mysteriously starts working again! Because the <abbr>HTTP</abbr> cache expired! Just like it’s supposed to! Kill me! Kill me now!)
<p>So here’s one thing you should absolutely do: reconfigure your web server so that your cache manifest file is not cacheable by <abbr>HTTP</abbr> semantics. If you’re running an Apache-based web server, these two lines in your <code>.htaccess</code> file will do the trick:
<pre><code>ExpiresActive On
ExpiresDefault "access"</code></pre>
<p>That will actually disable caching for every file in that directory and all subdirectories. That’s probably not what you want in production, so you should either qualify this with a <code><Files></code> directive so it only affects your cache manifest file, or create a subdirectory that contains nothing but this <code>.htaccess</code> file and your cache manifest file. As usual, configuration details vary by web server, so consult your server’s documentation for how to control <abbr>HTTP</abbr> caching headers.
<p>Once you’ve disabled <abbr>HTTP</abbr> caching on the cache manifest file itself, you’ll still have times where you’ve changed one of the resources in the appcache, but it’s still at the same <abbr>URL</abbr> on your web server. Here, step 2 of the three-phase process will screw you. If your cache manifest file hasn’t changed, the browser will never notice that one of the previously cached resources has changed. Consider the following example:
<pre><code>CACHE MANIFEST
# rev 42
clock.js
clock.css</code></pre>
<p>If you change <code>clock.css</code> and redeploy it, you won’t see the changes, because the cache manifest file itself hasn’t changed. Every time you make a change to one of the resources in your offline web application, you’ll need to change the cache manifest file itself. This can be as simple as changing a single character. The easiest way I’ve found to accomplish this is to include a comment line with a revision number. Change the revision number in the comment, then the web server will return the newly changed cache manifest file, your browser will notice that the contents of the file have changed, and it will kick off the process to re-download all the resources listed in the manifest.
<pre><code>CACHE MANIFEST
<mark># rev 43</mark>
clock.js
clock.css</code></pre>
<p class=a>❧
<h2 id=halma>Let’s Build One!</h2>
<p>Remember the Halma game that we introduced in <a href=canvas.html#halma>the canvas chapter</a> and later improved by <a href=storage.html#halma>saving state with persistent local storage</a>? Let’s take our Halma game offline.
<p>To do that, we need a manifest that lists all the resources the game needs. Well, there’s the main <abbr>HTML</abbr> page, a single JavaScript file that contains all the game code, and… that’s it. There are no images, because all the drawing is done programmatically via the <a href=canvas.html>canvas <abbr>API</abbr></a>. All the necessary <abbr>CSS</abbr> styles are in a <code><style></code> element at the top of the <abbr>HTML</abbr> page. So this is our cache manifest:
<pre><code>CACHE MANIFEST
halma.html
../halma-localstorage.js</code></pre>
<p>A word about paths. I’ve created an <code>offline/</code> subdirectory in the <code>examples/</code> directory, and this cache manifest file lives inside the subdirectory. Because the <abbr>HTML</abbr> page will need one minor addition to work offline (more on that in a minute), I’ve created a separate copy of the <abbr>HTML</abbr> file, which also lives in the <code>offline/</code> subdirectory. But because there are no changes to the JavaScript code itself since <a href=storage.html#halma>we added local storage support</a>, I’m literally reusing the same <code>.js</code> file, which lives in the parent directory (<code>examples/</code>). Altogether, the files look like this:
<pre><samp>/examples/localstorage-halma.html
/examples/halma-localstorage.js
/examples/offline/halma.manifest
/examples/offline/halma.html</samp></pre>
<p>In the cache manifest file (<code>/examples/offline/halma.manifest</code>), we want to reference two files. First, the offline version of the <abbr>HTML</abbr> file (<code>/examples/offline/halma.html</code>). Since these two files are in the same directory, it is listed in the manifest file without any path prefix. Second, the JavaScript file which lives in the parent directory (<code>/examples/halma-localstorage.js</code>). This is listed in the manifest file using relative <abbr>URL</abbr> notation: <code>../halma-localstorage.js</code>. This is just like you might use a relative <abbr>URL</abbr> in an <code><img src></code> attribute. As you’ll see in the next example, you can also use absolute paths (that start at the root of the current domain) or even absolute <abbr>URL</abbr>s (that point to resources on other domains).
<p>Now, in the <abbr>HTML</abbr> file, we need to add the <code>manifest</code> attribute that points to the cache manifest file.
<pre><code><!DOCTYPE html>
<html lang="en" <mark>manifest="halma.manifest"</mark>></code></pre>
<p>And that’s it! When an offline-capable browser first loads <a href=examples/offline/halma.html>the offline-enabled <abbr>HTML</abbr> page</a>, it will download the linked cache manifest file and start downloading all the referenced resources and storing them in the offline application cache. From then on, the offline application algorithm takes over whenever you revisit the page. You can play the game offline, and since it remembers its state locally, you can leave and come back as often as you like.
<p class=a>❧
<h2 id=further-reading>Further Reading</h2>
<p>Standards:
<ul>
<li><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html>Offline web applications</a> in the <abbr>HTML5</abbr> specification
</ul>
<p>Browser vendor documentation:
<ul>
<li><a href=https://developer.mozilla.org/En/Offline_resources_in_Firefox>Offline resources in Firefox</a>
<li><a href=http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/OfflineApplicationCache/OfflineApplicationCache.html><abbr>HTML5</abbr> offline application cache</a>, part of the <a href=http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Introduction/Introduction.html>Safari client-side storage and offline applications programming guide</a>
</ul>
<p>Tutorials and demos:
<ul>
<li><a href=http://googlecode.blogspot.com/2009/04/gmail-for-mobile-html5-series-using.html>Gmail for mobile <abbr>HTML5</abbr> series: using appcache to launch offline - part 1</a>
<li><a href=http://googlecode.blogspot.com/2009/05/gmail-for-mobile-html5-series-part-2.html>Gmail for mobile <abbr>HTML5</abbr> series: using appcache to launch offline - part 2</a>
<li><a href=http://googlecode.blogspot.com/2009/05/gmail-for-mobile-html5-series-part-3.html>Gmail for mobile <abbr>HTML5</abbr> series: using appcache to launch offline - part 3</a>
<li><a href=http://jonathanstark.com/blog/2009/09/27/debugging-html-5-offline-application-cache/>Debugging <abbr>HTML5</abbr> offline application cache</a>
<li><a href=http://hacks.mozilla.org/2010/02/an-html5-offline-image-editor-and-uploader-application/>an HTML5 offline image editor and uploader application</a>
<li><a href=http://www.20thingsilearned.com/>20 Things I Learned About Browsers and the Web</a>, an advanced demo that uses the application cache and other <abbr>HTML5</abbr> techniques
</ul>
<p class=a>❧
<p>This has been “Let’s Take This Offline.” The <a href=table-of-contents.html>full table of contents</a> has more if you’d like to keep reading.
<div class=pf>
<h4>Did You Know?</h4>
<div class=moneybags>
<blockquote><p>In association with Google Press, O’Reilly is distributing this book in a variety of formats, including paper, ePub, Mobi, and <abbr>DRM</abbr>-free <abbr>PDF</abbr>. The paid edition is called “HTML5: Up & Running,” and it is available now. This chapter is included in the paid edition.
<p>If you liked this chapter and want to show your appreciation, you can <a href="http://www.amazon.com/HTML5-Up-Running-Mark-Pilgrim/dp/0596806027?ie=UTF8&tag=diveintomark-20&creativeASIN=0596806027">buy “HTML5: Up & Running” with this affiliate link</a> or <a href=http://oreilly.com/catalog/9780596806033>buy an electronic edition directly from O’Reilly</a>. You’ll get a book, and I’ll get a buck. I do not currently accept direct donations.
</blockquote>
</div>
</div>
<p class=c>Copyright MMIX–MMXI <a href=about.html>Mark Pilgrim</a>
<form action=http://www.google.com/cse><div><input type=hidden name=cx value=017884302975346027366:bgclqh8nvse><input type=hidden name=ie value=UTF-8><input type=search name=q size=25 placeholder="powered by Google™"> <input type=submit name=sa value=Search></div></form>
<script src=j/jquery.js></script>
<script src=j/modernizr.js></script>
<script src=j/dih5.js></script>