forked from deianvasilev/diveintohtml5
-
Notifications
You must be signed in to change notification settings - Fork 10
/
storage.html
355 lines (253 loc) · 32.9 KB
/
storage.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
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
<!DOCTYPE html>
<meta charset=utf-8>
<title>Lokální úložiště - 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 7}
</style>
<link rel=stylesheet media='only screen and (max-device-width: 480px)' href=mobile.css>
<link rel=prefetch href=detect.html>
<p>Navigace: <a href=index.html>Domů</a> <span class=u>‣</span> <a href=table-of-contents.html#storage>Dive Into <abbr>HTML5</abbr></a> <span class=u>‣</span>
<h1><br>Minulost, současnost & budoucnost lokálního úložiště pro webové aplikace</h1>
<p id=toc>
<p class=a>❧
<h2 id=divingin>Jdeme na to</h2>
<p class=f><img src=i/aoc-t.png alt=P width=110 height=106>rvalé lokální úložiště je jednou z oblastí, kde měly nativní klientské aplikace (desktopové) výhodu nad webovými aplikacemi. Nativním aplikacím operační systém obvykle poskytuje abstraktní vrstvu pro ukládání a načítání dat specifických pro aplikace, jako jsou nastavení nebo běhové stavy. Jejich hodnoty mohou být uloženy v registrech, INI souborech, XML souborech, nebo na jiném místě v závislosti na platformě. Pokud vaše desktopová aplikace potřebuje lokální úložiště mimo formu klíč/hodnota, můžete připojit vlastní databázi, vymyslet vlastní souborový formát, nebo využít některé jiné řešení.
<p>Webové aplikace v minulosti neměly takovýto luxus. Cookies byly vynalezeny na začátku webové historie a dokonce je lze použít pro trvalé lokální ukládání malého množství dat. Ale mají tři potenciálně odrazující nevýhody:
<ul>
<li>Cookies jsou součástí každého <abbr>HTTP</abbr> požadavku, a tím zpomalují vaši webovou aplikaci zbytečným přenosem stále stejných dat
<li>Cookies jsou součástí každého požadavku <abbr>HTTP</abbr> a tím odesílají nezašifrovaná data přes internet (pokud není celá webová aplikace nabízena přes <abbr>SSL</abbr>)
<li>Cookies jsou omezeny na přibližně 4 kB dat - dost na zpomalení aplikace (viz výše), ale ne natolik, aby byly dostatečně užitečné
</ul>
<p>To, co skutečně chceme je:
<ul>
<li>hodně úložného prostoru
<li>na straně klienta
<li>který přetrvává i po obnovení stránky
<li>a není přenášen na server
</ul>
<p>Před <abbr>HTML5</abbr>, byly všechny pokusy o dosažení těchto cílů neuspokojivé.
<p class=a>❧
<h2 id=history>Stručná historie hacků lokálního úložiště před HTML5</h2>
<p>Na počátku byl jen Internet Explorer. Nebo přinejmenším Microsoft chtěl, aby si to svět myslel. Za tímto účelem v rámci <a href="http://en.wikipedia.org/wiki/Browser_wars#The_first_browser_war">První Velké Války Prohlížečů</a>, Microsoft vyvinul velké množství inovací a začlenil je do Internet Eploreru, prohlížeče, který měl válku prohlížečů ukončit. Jedna z těchto inovací se jmenuje <a href="http://msdn.microsoft.com/en-us/library/ms531078(v=VS.85).aspx"><abbr>DHTML</abbr> Behaviors</a> a jeden z těchto behaviorů (způsobů chování) se jmenuje <a href="http://msdn.microsoft.com/en-us/library/ms531424(VS.85).aspx">userData</a>.
<p><code>userData</code> umožňují webovým stránkám uložit až 64KB na jednu doménu, v hierarchické struktuře založené na XML. (Důvěryhodné domény jako jsou intranetové stránky, umožňují uložit 10krát víc dat. A <a href="http://en.wikiquote.org/wiki/Bill_Gates#Misattributed">640 KB by mělo být dost pro každého</a>.) IE nezobrazuje žádný povolovací dialog a není potřeba povolení na zvýšení úložného místa k využití.
<p>V roce 2002 Adobe představilo ve Flashi 6 funkci, která získala nešťastný a zavádějící název "Flash cookies." V prostředí Flashe je funkce spíše známá jako místní sdílené objekty (<a href="http://kb2.adobe.com/cps/161/tn_16194.html">Local Shared Objects</a>). Stručně řečeno, Flash objekt dovolil uložení až 100 KB dat na jednu doménu. Brad Neuberg vyvinul raný prototyp Flash-to-JavaScript můstku nazvaný <a href="http://codinginparadise.org/weblog/2005/10/amass-ajax-massive-storage-system.html">AMASS</a> (AJAX Massive Storage System), ale ten byl omezen některými návrhovými chybami Flashe. V roce 2006 s příchodem <a href="http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/external/ExternalInterface.html">ExternalInterface</a> Flashe 8, se stal přístup k <abbr>LSO</abbr> z JavaScriptu řádově jednodušším a rychlejším. Brad přepsal <abbr>AMASS</abbr> a integroval ho do populárního <a href=http://www.dojotoolkit.org/>Dojo Toolkitu</a> pod názvem <a href="http://api.dojotoolkit.org/jsdoc/HEAD/dojox.storage.manager"><code>dojox.storage</code></a>. Flash poskytuje každé doméně 100 KB úložistě "zdarma". Kromě toho vyzve uživatele k povolení každého požadavku na zvýšení prostoru pro ukládání dat (1 MB, 10 MB atd.).
<p>V roce 2007 Google uvedl <a href="http://gears.google.com/">Gears</a>, open source plugin pro prohlížeče zaměřený na rozšíření schopností prohlížečů. (Gears jsme již dříve zmínili v souvislosti s poskytováním <a href=geolocation.html#ie>geolokačniho <abbr>API</abbr> v Internet Exploreru</a>.) Gears poskytuje <a href="http://code.google.com/apis/gears/api_database.html"><abbr>API</abbr> pro vestavěnou <abbr>SQL</abbr> databázi</a> postavenou na <a href="http://www.sqlite.org/">SQLite</a>. Po jednom získání oprávnění od uživatele může Gears ukládat neomezené množství dat za doménu v tabulkách databáze <abbr>SQL</abbr>.
<p>Mezitím Brad Neuberg a jiní pokračovali dál ve snaze vyvinout z <code>dojox.storage</code> jednotné rozhraní pro všechny různé pluginy a <abbr>API</abbr>. Od roku 2009 <code>dojox.storage</code> automaticky detekuje (a současně zastřešuje jednotným rozhraním) Adobe Flash, Gears, Adobe AIR a raný prototyp skladování <abbr>HTML5</abbr>, které bylo implementováno pouze ve starších verzích Firefoxu.
<p>Pokud jste prozkumali tato řešení, objevíte podobnost: všechna řešení jsou buď specifická pro jediný prohlížeč, nebo závislá na pluginu třetí strany. Navzdory heroickému úsilí překlenout rozdíly (v <code>dojox.storage</code>), všechny vystavují radikálně odlišné rozhraní, mají různé skladovací omezení a představují různé uživatelské zkušenosti. To je tedy ten problém a <abbr>HTML5</abbr> ustanovuje řešení: zajistit standardizované <abbr>API</abbr> implementované nativně a důsledně ve více prohlížečích, aniž byste museli spoléhat na pluginy třetích stran.
<p class=a>❧
<h2 id=localstorage>Představujeme HTML5 úložiště</h2>
<p>To, co jsem si označil jako „<abbr>HTML5</abbr> Storage“, je specifikací pojmenované <a href="http://dev.w3.org/html5/webstorage/">Webové úložiště</a>, které bylo součástí základní <abbr>HTML5</abbr> specifikace, ale bylo vyčleněno do vlastní specifikace z nezajímavých politických důvodů. Někteří výrobci prohlížečů na něj také odkazují jako na „Local Storage“ nebo „<abbr>DOM</abbr> Storage.“ Situace s pojmenováváním se více komplikuje se souvisejícími podobně pojmenovanými nově vznikajícími standardy, které zmíním později v této kapitole.
<p>Takže, co je <abbr>HTML5</abbr> Storage? Jednoduše řečeno se jedná o způsob, jakým mohou webové stránky lokálně ukládat páry klíč/hodnota uvnitř webového prohlížeče. Stejně jako cookies i tato data přetrvávají po opuštění webové stránky, uzavření panelu prohlížeče, ukončení prohlížeče a tak podobně. Na rozdíl od cookies nejsou tato data nikdy přenášena na vzdálený server (pokud je tam nepošlete vy sami). Na rozdíl od všech <a href=#history>předchozích pokusů</a> o zajištění trvalého místního úložiště, je implementováno nativně ve webových prohlížečích, takže je k dispozici, i když nepoužíváte v prohlížeči pluginy třetích stran.
<p>O které prohlížeče se jedná? <abbr>HTML5</abbr> Storage podporuje poslední verze skoro každého prohlížeče… dokonce i Internet Explorer!
<table class=bc>
<caption><abbr>HTML5</abbr> Storage podporují</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>8.0+<td>3.5+<td>4.0+<td>4.0+<td>10.5+<td>2.0+<td>2.0+
</table>
<p>Z vašeho javascriptového kódu máte přístup do <abbr>HTML5</abbr> Storage přes objekt <code>localStorage</code> v objektu global <code>window</code>. Dříve než jej můžete začít používat, měli byste si <a href=detect.html#storage>ověřit, zda ho prohlížeč podporuje</a>.
<p class="legend top" style="padding-left:6em"><span class=arrow>↶</span> kontrola podpory <abbr>HTML5</abbr> Storage
<pre><code>function supports_html5_storage() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
}</code></pre>
<p>Než aby jste tuto funkci psali sami, můžete k zjištění podpory <abbr>HTML5</abbr> Storage použít <a href=detect.html#modernizr>Modernizr</a>.
<pre><code>if (<mark>Modernizr.localstorage</mark>) {
// window.localStorage je k dispozici!
} else {
// žádná nativní podpora pro HTML5 storage :(
// možná zkuste dojox.storage nebo řešení třetích stran
}</code></pre>
<p class=a>❧
<h2 id=methods>Používání HTML5 Storage</h2>
<p><abbr>HTML5</abbr> Storage je založen na párech klíč/hodnota. Uložíte-li data s pojmenovaným klíčem, pak můžete tato data se stejným klíčem získat. Pojmenovaný klíč je řetězec. Data mohou být jakéhokoliv typu, který JavaScript podporuje, včetně stringů, logických hodnot, celých čísel, nebo desetinných čísel. Nicméně data se vždy uloží jako řetězec. Pokud ukládáte nebo načítáte cokoliv jiného než řetězce, budete muset použít funkce jako <code>parseInt()</code> nebo <code>parseFloat()</code> k převedení načítaných dat do očekávaného JavaScriptového datového typu.
<pre><code>interface Storage {
getter any getItem(in DOMString key);
setter creator void setItem(in DOMString key, in any data);
};</code></pre>
<p>Volání <code>setItem()</code> s pojmenovaným klíčem, který již existuje, potichu přepíše přecházející uloženou hodnotu. Volání <code>getItem()</code> s neexistujícím klíčem vrátí <code>null</code> spíše než výjimku.
<p>Stejně jako ostatní JavaScriptové objekty, můžete považovat <code>localStorage</code> objekt jako asociativní pole. Namísto použití metody <code>getItem()</code> a <code>setItem()</code>, můžete jednoduše použít hranaté závorky. Například, tento kousek kódu:
<pre><code>var foo = localStorage.<mark>getItem</mark>("bar");
// ...
localStorage.<mark>setItem</mark>("bar", foo);</code></pre>
<p>…může být přepsán s použítím syntaxe hranatých závorek:
<pre><code>var foo = localStorage<mark>["bar"]</mark>;
// ...
localStorage<mark>["bar"]</mark> = foo;</code></pre>
<p>Existují rovněž metody pro odstranění hodnoty daného pojmenovaného klíče, a vyčištění celého úložného prostoru (což je odstranění všech klíčů a hodnot najednou).
<pre><code>interface Storage {
deleter void removeItem(in DOMString key);
void clear();
};</code></pre>
<p>Volání <code>removeItem()</code> s neexistujícím klíčem neprovede nic.
<p>Nakonec je zde vlastnost k získání celkového počtu hodnot v úložišti a k iteraci přes všechny klíče podle indexu (k získání názvu každého klíče).
<pre><code>interface Storage {
readonly attribute unsigned long length;
getter DOMString key(in unsigned long index);
};</code></pre>
<p>Pokud zavoláte <code>key()</code> s indexem mimo 0–(<code>délka</code>-1), tak funkce vrátí <code>null</code>.
<h3 id=storage-event>Sledování změn v HTML5 Storage Area</h3>
<p>Pokud chcete programově sledovat změny v prostoru úložiště, můžete odchytávat události <code>storage</code>. Události <code>storage</code> jsou vyhozeny z <code>window</code> objektu kdykoliv zavoláme <code>setItem()</code>, <code>removeItem()</code>, nebo <code>clear()</code> <em>a skutečně něco změníme</em>. Například, když nastavíte položku na její současnou hodnotu nebo zavoláte <code>clear()</code> pokud v úložišti nejsou žádné pojmenované klíče, tak <code>storage</code> nevyhodí událost, protože se ve skutečnosti nic v úložišti nezměnilo.
<p><code>Storage</code> událost je podporována všude, kde je podporován objekt <code>localStorage</code>, což zahrnuje i Internet Explorer 8. IE 8 nepodporuje W3C standard <code>addEventListener</code> (i když nakonec bylo přidáno v IE 9). Proto k zachycení událostí <code>storage</code>, musíte zkontrolovat který mechanismus událostí prohlížeč podporuje. (Pokud jste to už dříve dělali s jinými událostmi, můžete přejít na konec této části. Odchytávání událostí <code>storage</code> funguje stejně jako každá jiná událost, kterou jste dříve odchytávali. Pokud upředňostňujete užití jQuery nebo nějaké jiné javascriptové knihovny k obsluze událostí, můžete to s událostmi <code>storage</code> dělat stejně.)
<pre><code>if (window.addEventListener) {
window.addEventListener("storage", handle_storage, false);
} else {
window.attachEvent("onstorage", handle_storage);
};</code></pre>
<p>Zpětné volání <code>Handle_storage</code> funkce bude voláno s <code>StorageEvent</code> objektem, vyjímkou je Internet Explorer kde jsou události objektu uloženy ve <code>window.event</code>.
<pre><code>function handle_storage(e) {
if (!e) { e = window.event; }
}</code></pre>
<p>V tomto bodě bude proměnná <code>e</code> objektem <code>StorageEvent</code>, což má tyto užitečné vlastnosti.
<table class=st>
<caption>Objekt StorageEvent</caption>
<thead>
<tr class=ho><th>Vlastnost<th>Typ<th>Popis
<tbody>
<tr class=zebra><th><code>key</code><td>string<td>pojmenovaný klíč, který byl přidán, odstraněn nebo změněn
<tr><th><code>oldValue</code><td>jakýkoliv<td>předchozí hodnota (nyní přepsaná), nebo <code>null</code> pokud byla přidána nová položka
<tr class=zebra><th><code>newValue</code><td>jakýkoliv<td>nová hodnota, nebo <code>null</code> pokud byla položka odstraněna
<tr><th><code>url</code><sup>*</sup><td>string<td>stránka, kterou volala metoda, kterou spouští tato změna
<tfoot>
<tr><td colspan=3>* Poznámka: <code>url</code> vlastnost se původně jmenovala <code>uri</code>. Některé prohlížeče byly vydány s touto vlastností před změnou specifikace. Pro maximální kompatibilitu byste měli zkontrolovat zda <code>url</code> vlastnost podporuje a pokud ne, zkontrolujte podporu vlastnosti <code>uri</code>.
</table>
<p><code>Storage</code> akci nelze zrušit (not cancelable). V rámci zpetného volání funkce <code>handle_storage</code> neexistuje žádný způsob, jak zastavit změnu vyvolání. Je to prostě způsob jak prohlížeč říká „Hej, to se právě stalo. Neexistuje nic, co bys mohl udělat; Já jen chtěl abys to věděl.“
<h3 id=limitations>Omezení v současných prohlížečích</h3>
<p>Dříve, v části <a href=#history>o historii hacků místního úložiště</a> pomocí pluginů třetích stran, jsem se zmínil o omezeních jednotlivých technik, jako například omezení velikosti. Právě jsem si uvědomil, že jsem nezmínil nic o omezeních právě standardizovaného <abbr>HTML5</abbr> Storage. Nejdříve vám dám odpovědi a potom je vysvětlím. Odpovědi jsou, v pořadí podle důležitosti, „5 MB,“ „<code>QUOTA_EXCEEDED_ERR</code>,“ a „ne.“
<p>„5 MB“ je, úložný prostor, který dostane každý <a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/origin-0.html#origin-0>origin</a> ve výchozím nastavení. Překvapivě je to stejné napříč prohlížeči, ačkoli je to ve specifikaci <abbr>HTML5</abbr> Storage formulováno jen jako návrh. Jednu věc je důležité si zapamatovat, a to že ukládáte řetězce a ne data v původním formátu. Pokud ukládáte hodně celých nebo desetinných čísel, může být rozdíl v prezentaci skutečně velký. Každá číslice v desetinného čísla je uložena jako znak, ne jako běžná prezentace desetinného čísla.
<p>„<code>QUOTA_EXCEEDED_ERR</code>“ je výjimka, kterou dostanete, pokud překročíte kapacitu 5 MB úložného prostoru. „Ne“ je odpověď na další zřejmou otázku, „Mohu se zeptat uživatele na přidělení většího místa?“ V době psaní (Únor 2011) žádný prohlížeč nepodporuje jakýkoliv mechanismus pro webové vyvojáře, který by umožnil dotazání se na zvětšení uložného prostoru. Některé prohlížeče (<a href=http://dev.opera.com/articles/view/web-storage/>například Opera</a>) umožňují uživateli ovládat jak velké uložiště může každá stránka využívat, ale je to čistě uživatelem iniciovaná věc, ne něco co byste vy jako webový vývojář mohli vestavět do aplikace.
<p class=a>❧
<h2 id=halma>HTML5 Storage v akci</h2>
<p>Podívejme se na <abbr>HTML5</abbr> Storage v akci. Připomeňme <a href=canvas.html#halma>si hru Halma kterou jsme vytvořili v kapitole o canvasu</a>. S hrou je však malý problém: pokud zavřete okno prohlížeče uprostřed hry, ztratíte svůj postup. Ale s <abbr>HTML5</abbr> Storage můžeme rezehranou hru uložit lokálně v rámci samotného prohlížeče. Zde je <a href=examples/localstorage-halma.html>živá ukázka</a>. Zahrajte několik tahů, zavřete kartu prohlížeče a znovu ji otevřete. Pokud váš prohlížeč podporuje <abbr>HTML5</abbr> Storage, ukázková stránka si jako kouzlem zapamatuje stav vaší hry včetně počtu tahů, které jste táhli pozice každého kamene na desce a dokonce i to zda byl některý kámen vybrán.
<p>Jak to funguje? Pokaždé, když dojde ke změně ve hře, zavoláme tuto funkci:
<pre><code>function saveGameState() {
if (!supportsLocalStorage()) { return false; }
localStorage["halma.game.in.progress"] = gGameInProgress;
for (var i = 0; i < kNumPieces; i++) {
localStorage["halma.piece." + i + ".row"] = gPieces[i].row;
localStorage["halma.piece." + i + ".column"] = gPieces[i].column;
}
localStorage["halma.selectedpiece"] = gSelectedPieceIndex;
localStorage["halma.selectedpiecehasmoved"] = gSelectedPieceHasMoved;
localStorage["halma.movecount"] = gMoveCount;
return true;
}</code></pre>
<p>Jak můžete vidět, pokud je rozehraná hra využíváme k uložení objectu <code>localStorage</code> (<code>gGameInProgress</code>, logická hodnota). Pokud ano, projde pieces (<code>gPieces</code>, JavaScript <code>Array</code>) uloží čísla řádku a sloupce pro každého pieces. Poté uloží několik dalších stavů hry, včetně toho, který pieces je vybrán (<code>gSelectedPieceIndex</code>, celé číslo), zda je piece uprostřed potencionálně dlouhé řady skoků (<code>gSelectedPieceHasMoved</code>, a Boolean), a celkový počet odehraných tahů (<code>gMoveCount</code>, celé číslo).
<p>Při načtení stránky místo automatického volání funkce <code>newGame()</code>, která by resetovala proměnné na startovní hodnoty, zavoláme funkci <code>resumeGame()</code>. Pomocí <abbr>HTML5</abbr> Storage funkce <code>resumeGame()</code> zkontroluje, zda je lokálně uložen stav o rozehrané hře. Pokud ano, obnoví tyto hodnoty pomocí objektu <code>localStorage</code>.
<pre><code>function resumeGame() {
if (!supportsLocalStorage()) { return false; }
gGameInProgress = (localStorage["halma.game.in.progress"] == "true");
if (!gGameInProgress) { return false; }
gPieces = new Array(kNumPieces);
for (var i = 0; i < kNumPieces; i++) {
var row = parseInt(localStorage["halma.piece." + i + ".row"]);
var column = parseInt(localStorage["halma.piece." + i + ".column"]);
gPieces[i] = new Cell(row, column);
}
gNumPieces = kNumPieces;
gSelectedPieceIndex = parseInt(localStorage["halma.selectedpiece"]);
gSelectedPieceHasMoved = localStorage["halma.selectedpiecehasmoved"] == "true";
gMoveCount = parseInt(localStorage["halma.movecount"]);
drawBoard();
return true;
}</code></pre>
<p>Nejdůležitější částí této funkce je varování, které jsem zmiňoval dříve v této kapitole, které zde zopakuji: <em>Data jsou uložena jako řetězce. Pokud ukládáte něco jiného než řetězce, budete je muset změnit sami při načítání.</em> Například příznak, zda je hra rozehraná (<code>gGameInProgress</code>), je logická hodnota. Ve funkci <code>saveGameState()</code> jsme jej pouze uložili a nedělali jsme si hlavu s datatypem:
<pre><code>localStorage["halma.game.in.progress"] = <mark>gGameInProgress</mark>;</code></pre>
<p>Ale ve funkci <code>resumeGame()</code> je třeba považovat hodnotu, kterou jsme dostali od místního úložiště jako řetězec, a ručně ji přetvořit na správnou logickou hodnotu sami:
<pre><code>gGameInProgress = (localStorage["halma.game.in.progress"] <mark>== "true"</mark>);</code></pre>
<p>Stejně tak je počet tahů uložený v <code>gMoveCount</code> jako celé číslo. Ve funkci <code>saveGameState()</code> jsme jej prostě uložily:
<pre><code>localStorage["halma.movecount"] = <mark>gMoveCount</mark>;</code></pre>
<p>Ale ve funkci <code>resumeGame()</code> musíme změnit hodnotu na celé číslo pomocí funkce <code>parseInt()</code> vestavěné přímo v JavaScriptu:
<pre><code>gMoveCount = <mark>parseInt</mark>(localStorage["halma.movecount"]);</code></pre>
<p class=a>❧
<h2 id=future>Za hranicemi párů klíč - hodnota: soupeření vizí</h2>
<p>Zatímco <a href=#history>minulost je plná hacků a zástupných řešení</a>, současný stav <abbr>HTML5</abbr> Storage je překvapivě růžový. Nové <abbr>API</abbr> je standardizováno a implementováno ve všech hlavních prohlížečích, platformách a zařízeních. Pro webového vývojáře to je prostě něco, co není vidět každý den, že? Ale existuje něco důležitějšího než „5 megabajtů párů klíč/hodnota,“ a budoucnost trvalého lokálního úložiště je… jak bych to… no, existuje více soupeřících vizí.
<p>Jednou z vizí je zkratka, kterou už asi znáte : <abbr>SQL</abbr>. V roce 2007 Google spustil <a href=http://gears.google.com/>Gears</a>, open source plugin pro většinu prohlížečů, který zahrnoval vestavěnou databázi založenou na <a href=http://www.sqlite.org/>SQLite</a>. Tento časný prototyp měl později vliv na vytvoření specifikace <a href=http://dev.w3.org/html5/webdatabase/>Web SQL Database</a>. Web SQL Database (dříve známý jako „WebDB“) poskytuje tenký obal kolem <abbr>SQL</abbr> databáze, která vám umožní dělat věci jako je tato z JavaScriptu:
<p class="legend top" style="padding-left:3em"><span class=arrow>↶</span> actual working code in 4 browsers
<pre><code><mark>openDatabase</mark>('documents', '1.0', 'Local document storage', 5*1024*1024, function (db) {
db.changeVersion('', '1.0', function (t) {
t.<mark>executeSql</mark>('CREATE TABLE docids (id, name)');
}, error);
});</code></pre>
<p>Jak vidíte většina akce spočívá v řetězci, který předáte metodě <code>executeSql</code>. Tento řetězec může být jakýkoliv podporovaný <abbr>SQL</abbr>, včetně <code>SELECT</code>, <code>UPDATE</code>, <code>INSERT</code> a <code>DELETE</code>. Je to jako klasické programování databází, kromě toho, že to děláte z JavaScriptu! Jaká radost!
<p>Specifikace Web SQL Database byla implementována do čtyř prohlížečů a platforem.
<table class=bc>
<caption>Podpora Web SQL Database</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>·<td>4.0+<td>4.0+<td>10.5+<td>3.0+<td>2.0+
</table>
<p>Samozřejmě, pokud jste v životě použili více než jeden databázový produkt, jste si vědomi, že <abbr>SQL</abbr> je víc termín marketingu než tvrdého-a-rychlého standardu. (Někdo by mohl říct totéž o „HTML5,“ ale to nevadí.) Jistě, je zde aktuální specifikace <abbr>SQL</abbr> (jmenuje se <a href="http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt">SQL-92</a>), ale na světě není databázový server, který odpovídá této a pouze této specifikaci. Máme Oracle <abbr>SQL</abbr>, Microsoft <abbr>SQL</abbr>, MySQL <abbr>SQL</abbr>, PostgreSQL <abbr>SQL</abbr>, a SQLite <abbr>SQL</abbr>. Opravdu, každý z těchto produktů v průběhu doby přidával nové <abbr>SQL</abbr> funkce, takže říkat „SQLite <abbr>SQL</abbr>“, nestačí abychom mohli upřesnily o čem mluvíme. Musíte říct: „verze <abbr>SQL</abbr> dodaná s SQLite verze X.Y.Z.“
<p>Toto nás přivádí k následujícímu prohlášení, v současné době uvedenému v horní části specifikace Web SQL Database:
<blockquote>
<p>Tato specifikace se dostala do slepé uličky: všichni zaiteresovaní implementátoři použili stejný SQL (Sqlite), ale je potřeba více nezávislých implementací, aby bylo možno pokračovat ve standardizační cestě. Dokud jiný implementátor nebude mít zájem implemnentovat tuto specifikaci, je popis dialektu SQL ponechán jednoduše jen jako odkaz na SQLite, což pro standard není přijatelné.
</blockquote>
<p>Vzhledem k těmto okolnostem vám přestavím další vizi pro pokročilé trvalé lokalní úložiště pro webové aplikace: <a href=http://dev.w3.org/2006/webapi/IndexedDB/><abbr>API</abbr> Indexované Databáze</a>, dříve známé jako „WebSimpleDB,“ nyní důvěrně známé jako „IndexedDB.“
<p><abbr>API</abbr> Indexované Databáze odhalují to co se nazývá <em>object store</em>. Object store sdílí mnoho konceptů s databází <abbr>SQL</abbr>. Jsou zde „databáze“ se „záznamy,“ a každý záznam má stanovený počet „polí.“ Každé pole má specifikovaný datový typ, který je definován při vytváření databáze. Můžete si vybrat podmnožinu záznamů, poté je vypočítávat „kurzorem.“ Změny v object store jsou řešeny v rámci „operace.“
<p>Pokud jste někdy dělali databázové <abbr>SQL</abbr> programování, tak vám tyto termíny pravděpodobně znějí povědomě. Hlavní rozdíl je v tom, že object store nemá žádný strukturovaný dotazovací jayzk. Nevytváříte dotazy typu <code>"SELECT * from USERS where ACTIVE = 'Y'"</code>. Místo toho můžete použít metodu uvedenou v object store otevření kurzoru nad databází s názvem „<code>USERS</code>,“ projít skrz záznamy, vyfiltrovat pryč záznamy s neaktivními uživateli a použít přístupovou metodu k získání hodnot každého ze zbývajích záznamů. <a href="http://hacks.mozilla.org/2010/06/comparing-indexeddb-and-webdatabase/">Dřívější průvodce po IndexedDB</a> je dobrý tutorial o fungování IndexedDB , porovnávající IndexedDB a Web SQL Database.
<p>V době psaní této knihy je IndexedDB implementováno pouze v <a href=https://developer.mozilla.org/en/Firefox_4_for_developers>beta verzi Firefox 4</a>. (Navzdory tomu, že Mozilla říkala <a href="http://hacks.mozilla.org/2010/06/beyond-html5-database-apis-and-the-road-to-indexeddb/">nikdy nebudeme implementovat Web SQL Database</a>.) Google uvedl, <a href="http://www.chromium.org/developers/design-documents/indexeddb">že uvažuje o podpoře IndexedDB</a> pro Chromium a Google Chrome. A dokonce i Microsoft říkal, že IndexedDB „<a href="http://blogs.msdn.com/b/ie/archive/2010/03/09/working-with-the-html5-community.aspx">je skvělé řešení pro web</a>.“
<p>Co tedy můžete jako webový vývojář dělat s IndexedDB? V současné době prakticky nic jiného než nějaké technologické demo. Ode dneška za rok? Možná něco. Podívejte se na „Další Čtení“, sekce s linky, na některé dobré tutorialy jak začít.
<p class=a>❧
<h2 id=further-reading>Další čtení</h2>
<p><abbr>HTML5</abbr> storage:
<ul>
<li><a href="http://dev.w3.org/html5/webstorage/"><abbr>HTML5</abbr> Storage</a> specifikace
<li><a href="http://msdn.microsoft.com/en-us/library/cc197062(VS.85).aspx">Introduction to DOM Storage</a> na <abbr>MSDN</abbr>
<li><a href="http://dev.opera.com/articles/view/web-storage/">Web Storage: easier, more powerful client-side data storage</a> na Opera Developer Community
<li><a href="https://developer.mozilla.org/en/dom/storage">DOM Storage</a> na Mozilla Developer Center. (Poznámka: Většina této stránky je věnována implementaci Firefox prototypu <code>globalStorage</code> objektu, nestandardního předchůdce <code>localStorage</code>. Mozilla přidala podporu pro standardní <code>localStorage</code> rozhraní do Firefox 3.5.)
<li><a href="http://www.ibm.com/developerworks/xml/library/x-html5mobile2/">Unlock local storage for mobile Web applications with HTML5</a>, tutorial na IBM DeveloperWorks
</ul>
<p>Raná práce Brad Neuberga <i>et. al.</i> (pre-<abbr>HTML5</abbr>):
<ul>
<li><a href="http://codinginparadise.org/weblog/2005/08/ajax-internet-explorer-has-native.html">Internet Explorer Has Native Support for Persistence?!?!</a> (o <code>userData</code> objectu v IE)
<li><a href="http://docs.google.com/View?docid=dhkhksk4_8gdp9gr#dojo_storage">Dojo Storage</a>, část většího tutorialu o (nyní zaniklé) Dojo Offline library
<li><a href="http://api.dojotoolkit.org/jsdoc/HEAD/dojox.storage.manager"><code>dojox.storage.manager</code> <abbr>API</abbr> reference</a>
<li><a href="http://svn.dojotoolkit.org/src/dojox/trunk/storage/">dojox.storage</a> Subversion repositář
</ul>
<p>Web SQL Database:
<ul>
<li><a href="http://dev.w3.org/html5/webdatabase/">Web SQL Database</a> specifikace
<li><a href="http://html5doctor.com/introducing-web-sql-databases/">Introducing Web <abbr>SQL</abbr> Databases</a>
<li><a href="http://html5demos.com/database">Web Database demonstration</a>
<lI><a href="http://zef.me/2774/persistence-js-an-asynchronous-javascript-orm-for-html5gears">persistence.js</a>, „asynchronous JavaScript <abbr>ORM</abbr>“ postavený na Web <abbr>SQL</abbr> Database a Gears
</ul>
<p>IndexedDB:
<ul>
<li><a href="http://dev.w3.org/2006/webapi/IndexedDB/">Indexed Database <abbr>API</abbr></a> specifikace
<li><a href="http://hacks.mozilla.org/2010/06/beyond-html5-database-apis-and-the-road-to-indexeddb/">Beyond HTML5: Database APIs and the Road to IndexedDB</a>
<li><a href="http://hacks.mozilla.org/2010/06/comparing-indexeddb-and-webdatabase/">Firefox 4: An early walk-through of IndexedDB</a>
</ul>
<p class=a>❧
<p>Toto byla „Minulost, současnost & budoucnost Lokálního Úložiště pro Webové Aplikace.“ Pokud budete chtít pokračovat ve čtení, přejděte na <a href=table-of-contents.html>celý obsah knihy</a>.
<div class=pf>
<h4>Víte že?</h4>
<div class=moneybags>
<blockquote><p>Ve spolupráci s Google Press, O’Reilly nabízí anglickou verzi této knihy v řadě formátů včetně tištěné podoby, ePub, Mobi a <abbr>PDF</abbr> bez <abbr>DRM</abbr>. Placená verze se jmenuje „HTML5: Up & Running,“ a můžete ji mít ihned. Tato kapitola je zahrnuta v placené verzi.
<p>Pokud se vám tahle kapitola líbila a chcete autora anglického originálu podpořit <a href="http://www.amazon.com/HTML5-Up-Running-Mark-Pilgrim/dp/0596806027?ie=UTF8&tag=diveintomark-20&creativeASIN=0596806027">kupte si „HTML5: Up & Running“ skrz tento affiliate odkaz</a> nebo <a href=http://oreilly.com/catalog/9780596806033>elektronickou verzi přímo od O’Reilly</a>.
</blockquote>
</div>
</div>
<p class=c>Copyright MMIX–MMXI <a href=about.html>Mark Pilgrim</a>, český překlad <a href="http://www.koudelavojtech.cz/">Vojtěch Koudela</a>
<form action=http://www.google.com/cse><div><input type=hidden name=cx value=013556084273090989037:f1s-wnbz68q><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=Hledat></div></form>
<script src=j/jquery.js></script>
<script src=j/modernizr.js></script>
<script src=j/dih5.js></script>
<script type="text/javascript"><!--
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25728182-1']);
_gaq.push(['_setDomainName', '.html5.cz']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
// --></script>