Tytuł oryginału: JavaScript Web Applications
Tłumaczenie: Daniel Kaczmarek
ISBN: 978-83-246-3887-1
© 2012 Helion S.A.
Authorized Polish translation of the English edition of JavaScript Web Applications, 1st Edition
9781449303518 © 2011 Alex MacCaw
This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all
rights to publish and sell the same.
All rights reserved. No part of this book may be reproduced or transmitted in any form or by any
means, electronic or mechanical, including photocopying, recording or by any information storage
retrieval system, without permission from the Publisher.
Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej
publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną,
fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje
naruszenie praw autorskich niniejszej publikacji.
Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich
właścicieli.
Wydawnictwo HELION dołożyło wszelkich starań, by zawarte w tej książce informacje były
kompletne i rzetelne. Nie bierze jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za
związane z tym ewentualne naruszenie praw patentowych lub autorskich. Wydawnictwo HELION nie
ponosi również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji
zawartych w książce.
Wydawnictwo HELION
ul. Kościuszki 1c, 44-100 GLIWICE
tel. 32 231 22 19, 32 230 98 63
e-mail: helion@helion.pl
WWW: http://helion.pl (księgarnia internetowa, katalog książek)
Pliki z przykładami omawianymi w książce można znaleźć pod adresem:
ftp://ftp.helion.pl/przyklady/jascww.zip
Drogi Czytelniku!
Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres
http://helion.pl/user/opinie/jascww
Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję.
Printed in Poland.
3
Spis treci
Przedmowa ...............................................................................................................................9
1. MVC
i
klasy ....................................................................................................................17
Pocztki
17
Nadawanie struktury
18
Czym jest MVC?
19
Model
19
Widok
20
Kontroler 21
Ku modularyzacji, tworzenie klas
22
Dodawanie funkcji do klas
23
Dodawanie metod do wasnej biblioteki klas
24
Dziedziczenie klas przy uyciu prototypu
25
Dodawanie dziedziczenia do biblioteki klas
26
Wywoywanie funkcji
27
Kontrola zasigu we wasnej bibliotece klas
29
Dodawanie funkcji prywatnych
31
Biblioteki klas
32
2. Zdarzenia i ich nasuchiwanie ....................................................................................35
Nasuchiwanie zdarze
35
Kolejno zdarze
36
Anulowanie zdarze
37
Obiekt zdarzenia Event
37
Biblioteki zdarze
39
Zmiana kontekstu
40
Delegowanie zdarze
40
Wasne zdarzenia
41
Wasne zdarzenia i moduy rozszerzajce jQuery
41
Zdarzenia inne ni zdarzenia DOM
43
Kup książkę
Poleć książkę
4
_ Spis
treci
3. Modele
i dane ..............................................................................................................47
MVC i przestrzenie nazw
47
Tworzenie ORM
48
Dziedziczenie przez prototypy
49
Dodawanie waciwoci ORM
50
Utrzymywanie rekordów
51
Dodawanie obsugi identyfikatorów
52
Adresowanie odwoa
53
adowanie danych
54
Wplatanie danych
55
adowanie danych przy uyciu Ajax
55
JSONP
59
Bezpieczestwo da midzy domenami
59
Wypenienie ORM danymi
60
Przechowywanie danych lokalnie
60
Dodanie mechanizmu przechowywania danych lokalnie do ORM
61
Przesyanie nowych rekordów na serwer
63
4. Kontrolery
i stany ........................................................................................................65
Wzorzec moduu
66
Import zmiennych globalnych
66
Eksport zmiennych globalnych
66
Dodawanie kontekstu
67
Wydzielanie kodu do oddzielnej biblioteki
68
adowanie kontrolerów po zaadowaniu dokumentu
69
Dostp do widoków
70
Delegowanie zdarze
72
Maszyny stanów
74
Routing
76
Korzystanie z hash value adresu URL
76
Wykrywanie zmian hash value
77
Ajax Crawling
77
Wykorzystanie API History HTML5
78
5. Widoki
i szablony ........................................................................................................ 81
Dynamiczne generowanie widoków
81
Szablony
82
Pomocnicze funkcje obsugi szablonów
84
Przechowywanie szablonów
85
Wizanie
86
Wizanie modeli
87
Kup książkę
Poleć książkę
Spis treci
_
5
6. Zarzdzanie
zalenociami .........................................................................................89
CommonJS
90
Deklarowanie moduu
90
Moduy i przegldarka
91
Biblioteki adowania moduów
92
Yabble
92
RequireJS 93
Opakowywanie moduów
94
Rozwizania alternatywne wzgldem moduów
95
LABjs
96
FUBC
96
7. Praca
z
plikami ............................................................................................................. 97
Obsuga w przegldarkach
97
Pobieranie informacji na temat plików
98
Kontrolka do przesyania plików na serwer
98
Przeciganie i upuszczanie
99
Przeciganie 100
Upuszczanie 101
Anulowanie domylnej obsugi przecigania i upuszczania
102
Kopiowanie i wklejanie
103
Kopiowanie 103
Wklejanie 104
Czytanie plików
105
Due obiekty binarne oraz fragmenty pliku
106
Wasne przyciski przegldarki
107
adowanie plików na serwer
107
ledzenie postpu operacji
109
Przesyanie pliku na serwer przy uyciu przecigania i upuszczania
oraz biblioteki jQuery
111
Obszar upuszczania
111
Przesyanie pliku na serwer
111
8. Praca w sieci w czasie rzeczywistym .........................................................................113
Historia dziaania w czasie rzeczywistym
113
WebSockets 114
Node.js i Socket.IO
118
Architektura czasu rzeczywistego
119
Odczuwana prdko dziaania
121
Kup książkę
Poleć książkę
6
_ Spis
treci
9. Testowanie i usuwanie bdów ................................................................................ 123
Testy jednostkowe
125
Asercje
125
QUnit
126
Jasmine
129
Sterowniki
131
Testowanie niezalene
134
Zombie
134
Ichabod
136
Testowanie rozproszone
137
wiadczenie wsparcia
137
Inspektory
138
Web Inspector
138
Firebug
140
Konsola
141
Funkcje pomocnicze konsoli
142
Uywanie debuggera
143
Analiza da sieciowych
144
Profilowanie i analiza czasu
145
10. Wdraanie .................................................................................................................. 149
Wydajno
149
Wykorzystanie pamici podrcznej
150
Minifikacja
152
Kompresja Gzip
153
Korzystanie z CDN
154
Audytory
155
Zasoby
156
11. Biblioteka
Spine
..........................................................................................................157
Instalacja
157
Klasy
158
Tworzenie instancji
158
Rozszerzanie klas
159
Kontekst 160
Zdarzenia
161
Modele
161
Pobieranie rekordów
163
Zdarzenia modelu
163
Weryfikacja poprawnoci
164
Zapisywanie 164
Kup książkę
Poleć książkę
Spis treci
_
7
Kontrolery
166
Wskazywanie kontekstu
167
Waciwo elements
167
Delegowanie zdarze
168
Zdarzenia kontrolera
168
Zdarzenia globalne
169
Wzorzec Render
170
Wzorzec Element
170
Aplikacja do zarzdzania danymi kontaktowymi
171
Model Contact
173
Kontroler Sidebar
173
Kontroler Contacts
175
Kontroler App
178
12. Biblioteka
Backbone .................................................................................................. 179
Modele
180
Modele i atrybuty
180
Kolekcje
181
Kontrola kolejnoci elementów w kolekcji
183
Widoki
183
Generowanie widoków
184
Delegowanie zdarze
184
Wizanie i kontekst
185
Kontrolery
186
Synchronizacja z serwerem
188
Wypenianie kolekcji
189
Po stronie serwera
189
Implementacja wasnej logiki
190
Aplikacja do zarzdzania list rzeczy do zrobienia
192
13. Biblioteka
JavaScriptMVC ......................................................................................... 199
Konfiguracja 200
Klasy
200
Tworzenie instancji
200
Wywoywanie metody bazowej
201
Okrelanie kontekstu
201
Dziedziczenie statyczne
201
Introspekcja 202
Przykadowy model
202
Kup książkę
Poleć książkę
8
_ Spis
treci
Model
203
Atrybuty i dane obserwowalne
203
Rozszerzanie modeli
205
Metody ustawiajce wartoci
205
Wartoci domylne
206
Metody pomocnicze
206
Enkapsulacja usug
207
Przeksztacanie typów
209
Zdarzenia CRUD
210
Wykorzystanie w widokach szablonów dziaajcych po stronie klienta
210
Sposób uycia
211
Modyfikatory jQuery
211
adowanie widoku ze znacznika skryptu
212
$.View i subszablony
212
Obiekty wstrzymane
212
Pakowanie, adowanie wstpne i wydajno
213
$.Controller: fabryka moduów rozszerzajcych jQuery
213
Informacje ogólne
215
Tworzenie instancji kontrolera
216
Wizanie zdarze
216
Akcje szablonowe
217
Kompletne rozwizanie: abstrakcyjna lista czynnoci CRUD
218
A. Wprowadzenie
do
biblioteki jQuery ........................................................................ 221
B. Rozszerzenia CSS ....................................................................................................... 231
C. Przegld CSS3 ............................................................................................................235
Skorowidz .............................................................................................................................255
Kup książkę
Poleć książkę
47
ROZDZIA 3.
Modele i dane
Gdy aplikacja ma utrzymywa stan na kliencie, jednym z wyzwa stojcym przed programi-
st jest zapewnienie odpowiedniego zarzdzania danymi. Standardowo w momencie wy-
woania strony dane pobiera si bezporednio z bazy danych, a wynik ich przetwarzania
umieszcza si bezporednio na stronie. Jednak w stanowych aplikacjach JavaScript proces za-
rzdzania danymi przebiega zupenie inaczej. Nie obowizuje w nich model wywoanie-
odpowied, nie s take dostpne zmienne na serwerze. Dane s za to pobierane zdalnie i tym-
czasowo przechowywane po stronie klienta.
Wprawdzie zaimplementowanie odpowiedniego mechanizmu moe by do trudnym za-
daniem, jednak uzyska si dziki temu co najmniej kilka korzyci. Na przykad dostp do da-
nych znajdujcych si po stronie klienta jest praktycznie natychmiastowy, tak jakby dane po-
bierane byy z pamici. Moe to zdecydowanie poprawi dziaanie interfejsu aplikacji, poniewa
kada czynno uytkownika skutkuje natychmiastowym zwróceniem wyniku. Dziki temu
aplikacja znajduje zdecydowanie wiksze uznanie u uytkowników.
Aby odpowiednio skonstruowa mechanizm przechowywania danych po stronie klienta,
trzeba najpierw szczegóowo przeanalizowa wszystkie okolicznoci. Zadanie najeone jest
rónorodnymi przeszkodami i puapkami, w które wpadaj zwaszcza pocztkujcy progra-
mici — szczególnie gdy ich aplikacje coraz bardziej si rozrastaj. W tym rozdziale zoba-
czymy, jak w najbardziej efektywny sposób zaimplementowa przechowywanie danych po
stronie klienta. Wskazane zostan take najbardziej zalecane wzorce i praktyki.
MVC i przestrzenie nazw
Aby opracowa tak architektur aplikacji, która bdzie przejrzysta i atwa w utrzymaniu,
trzeba przede wszystkim zapewni pen separacj widoków aplikacji, jej stanu i danych.
W przypadku wykorzystania wzorca MVC zarzdzanie danymi odbywa si w modelu („M”
w nazwie MVC). Modele powinny by rozczne wzgldem widoków i kontrolerów. Natomiast
logika wyznaczajca sposób manipulowania danymi oraz odpowiedzialna za zachowanie
aplikacji powinna by osadzona w modelu oraz oznaczona odpowiedni przestrzeni nazw.
W JavaScripcie odpowiedni przestrze nazw dla funkcji i zmiennych mona zapewni przez
uczynienie ich waciwociami obiektu. Na przykad:
var User = {
records: [
/* ... */ ]
};
Kup książkę
Poleć książkę
48
_
Rozdzia 3. Modele i dane
Tablica uytkowników ma teraz odpowiedni przestrze nazw
User.records
. Funkcje zwiza-
ne z obsug uytkowników równie mog nalee do przestrzeni nazw wyznaczanej przez
model
User
. Mona na przykad zaimplementowa funkcj
fetchRemote()
, która bdzie pobiera
z serwera dane uytkownika:
var User = {
records: [],
fetchRemote: function(){
/* ... */ }
};
Umieszczenie wszystkich waciwoci modelu w przestrzeni nazw zapewni, e nie wystpi
adne konflikty, a jednoczenie utrzymana zostanie zgodno z paradygmatem MVC. Poza
tym zmniejszy si zagroenie, e tworzony kod ródowy zamieni si z biegiem czasu w nie-
zrozumia spiral funkcji i wywoa zwrotnych.
Zakres wykorzystania przestrzeni nazw mona jeszcze pogbi i umieci wszystkie funkcje
operujce na instancjach uytkowników w rzeczywistych obiektach uytkowników. Przyjmij-
my, e na rekordzie uytkownika zaimplementowana jest funkcja
destroy()
. Odnosi si ona
do konkretnego uytkownika, zatem powinna by wywoywana na instancji obiektu
User
:
var user = new User;
user.destroy()
Aby osign zamierzony efekt, naley uczyni z
User
klas, a nie zwyky obiekt:
var User = function(atts){
this.attributes = atts || {};
};
User.prototype.destroy = function(){
/* ... */
};
Natomiast wszelkie funkcje i waciwoci, które nie dotycz konkretnego uytkownika, mog
by waciwociami bezporednio obiektu
User
:
User.fetchRemote = function(){
/* ... */
};
Wicej ciekawych informacji na temat przestrzeni nazw mona znale na blogu Petera
Michaux, który opublikowa bardzo ciekawy artyku na ten wanie temat (http://michaux.ca/
articles/javascript-namespacing).
Tworzenie ORM
Biblioteki odwzorowa obiektowo-relacyjnych, czyli ORM, s zwykle wykorzystywane w j-
zykach programowania innych ni JavaScript. Stanowi one jednak bardzo przydatne narz-
dzia do zarzdzania danymi, a take znacznie uatwiaj uycie modeli w aplikacji JavaScript.
Za pomoc ORM mona na przykad powiza model ze zdalnym serwerem — w wyniku
takiego powizania wszelkie zmiany w instancjach modelu bd wysyane w tle do serwera
w ramach wywoa Ajax. Mona take powiza instancj modelu z elementem HTML, dziki
czemu wszelkie zmiany w instancji modelu spowoduj odpowiedni zmian w widoku.
Przykady te zostan rozwinite nieco póniej, a na razie zobaczmy, jak tworzy si ORM.
Kup książkę
Poleć książkę
Tworzenie ORM
_
49
Zasadniczo ORM jest po prostu warstw obiektów opakowujc jakie dane. Standardowo
ORM stanowi warstw abstrakcji dla baz danych SQL, jednak w naszym przypadku ORM
bdzie po prostu warstw abstrakcji dla typów danych JavaScriptu. Zalet takiej dodatkowej
warstwy jest to, e podstawowy zbiór danych mona rozszerzy o dodatkowe rozwizania
przez dodanie wasnych funkcji i waciwoci. Dziki temu mona dodawa mechanizmy wery-
fikacji poprawnoci albo utrzymywania danych, obserwatory czy wywoania zwrotne do ser-
wera, a jednoczenie nadal mie moliwo wielokrotnego wykorzystywania kodu ródowego.
Dziedziczenie przez prototypy
Do stworzenia naszej wasnej biblioteki ORM wykorzystamy
Object.create()
, co jest podej-
ciem nieco odmiennym od przykadów opisywanych w rozdziale 1, w których korzystali-
my z klas. Nowe podejcie pozwoli nam jednak na skorzystanie z dziedziczenia przez pro-
totypy zamiast uywania funkcji konstruktorów i sowa kluczowego
new
.
Funkcja
Object.create()
przyjmuje jeden argument — obiekt prototypu — i zwraca nowy
obiekt z przekazanym obiektem prototypu. Inaczej mówic, przekazuje si do niej obiekt,
a funkcja zwraca nowy obiekt, potomny po obiekcie przekazanym.
Funkcja
Object.create()
zostaa dopiero niedawno dodana do specyfikacji ECMAScript, 5th
Edition i dlatego jeszcze nie wszystkie przegldarki j obsuguj — naley do nich midzy
innymi IE. Nie jest to jednak wielki problem, poniewa w razie potrzeby obsug tej funkcji
mona zaimplementowa samemu:
if (typeof Object.create !== "function")
Object.create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
Powyszy przykad pochodzi z artykuu Douglasa Crockforda na temat dziedziczenia przez
prototypy (http://javascript.crockford.com/prototypal.html). Warto si z nim zapozna, aby lepiej
pozna mechanizmy rzdzce prototypami i dziedziczeniem w jzyku JavaScript.
Utworzymy teraz obiekt
Model
, którego zadaniem bdzie tworzenie nowych modeli i instancji:
var Model = {
inherited: function(){},
created: function(){},
prototype: {
init: function(){}
},
create: function(){
var object = Object.create(this);
object.parent = this;
object.prototype = object.fn = Object.create(this.prototype);
object.created();
this.inherited(object);
return object;
},
init: function(){
var instance = Object.create(this.prototype);
Kup książkę
Poleć książkę
50
_
Rozdzia 3. Modele i dane
instance.parent = this;
instance.init.apply(instance, arguments);
return instance;
}
};
Programistów, którzy nie poznali dotychczas funkcji
Object.create()
, definicja
Model
moe
nieco zniechca, wic rozoymy j na czynniki pierwsze. Funkcja
create()
zwraca nowy
obiekt, który dziedziczy po obiekcie
Model
. W ten sposób tworzone bd nowe modele. Funkcja
init()
zwraca natomiast nowy obiekt, który dziedziczy po
Model.prototype
— czyli instancj
obiektu
Model
:
var Asset = Model.create();
var User = Model.create();
var user = User.init();
Dodawanie waciwoci ORM
Jeli teraz do
Model
dodamy waciwoci, stan si one dostpne we wszystkich modelach
potomnych:
// Dodanie waciwoci obiektu
jQuery.extend(Model, {
find: function(){}
});
// Dodanie waciwoci instancji
jQuery.extend(Model.prototype, {
init: function(atts) {
if (atts) this.load(atts);
},
load: function(attributes){
for(var name in attributes)
this[name] = attributes[name];
}
});
Metoda
jQuery.extend()
odpowiada wykonaniu ptli
for
i wykonaniu w niej rcznego kopio-
wania waciwoci. Tak wanie postpujemy w funkcji
load()
. Teraz waciwoci obiektu
i instancji s propagowane w dó, do konkretnych modeli:
assertEqual( typeof Asset.find, "function" );
W praktyce liczba dodawanych waciwoci bdzie do znaczna, dlatego najlepiej jest od razu
zawrze w obiekcie
Model
funkcje
extend()
i
include()
:
var Model = {
/* ... cicie ... */
extend: function(o){
var extended = o.extended;
jQuery.extend(this, o);
if (extended) extended(this);
},
include: function(o){
var included = o.included;
jQuery.extend(this.prototype, o);
if (included) included(this);
Kup książkę
Poleć książkę
Tworzenie ORM
_
51
}
};
// Dodanie waciwoci obiektu
Model.extend({
find: function(){}
});
// Dodanie waciwoci instancji
Model.include({
init: function(atts) {
/* ... */ },
load: function(attributes){
/* ... */ }
});
Mona ju zatem tworzy nowe zasoby i ustawia ich atrybuty:
var asset = Asset.init({name: "foo.png"});
Utrzymywanie rekordów
Potrzebny jest równie mechanizm utrzymywania rekordów, to znaczy zapamitywania od-
woa do utworzonych instancji, aby móc z nich korzysta w póniejszym czasie. Do tego
celu wykorzystany zostanie obiekt
records
ustawiony w modelu
Model
. Obiekt bdzie dodawany
do modelu w momencie zapisywania instancji modelu i usuwany z obiektu modelu, gdy usu-
wana bdzie instancja modelu:
// Obiekt z zapisanymi zasobami
Model.records = {};
Model.include({
newRecord: true,
create: function(){
this.newRecord = false;
this.parent.records[this.id] = this;
},
destroy: function(){
delete this.parent.records[this.id];
}
});
A w jaki sposób mona zmienia istniejc instancj? To proste — wystarczy zmieni odwo-
anie do obiektu:
Model.include({
update: function(){
this.parent.records[this.id] = this;
}
});
Warto take zaimplementowa wygodn funkcj odpowiedzialn za zapisywanie instancji,
tak by nie trzeba byo póniej sprawdza, czy instancja zostaa zapisana ju wczeniej albo
czy trzeba t instancj utworzy:
// Zapisanie obiektu do records i zapamitanie odwoania do obiektu
Model.include({
save: function(){
this.newRecord ? this.create() : this.update();
}
});
Kup książkę
Poleć książkę
52
_
Rozdzia 3. Modele i dane
Wreszcie dobrze te zaimplementowa funkcj
find()
, która bdzie wyszukiwa zasoby o wska-
zanym identyfikatorze:
Model.extend({
// Znalezienie zasobu o danym ID lub rzucenie wyjtku
find: function(id){
return this.records[id] || throw("Rekord nieznany");
}
});
ORM w najprostszej postaci jest ju gotowy, mona go zatem wykorzysta w praktyce:
var asset = Asset.init();
asset.name = "taki sam, taki sam";
asset.id = 1
asset.save();
var asset2 = Asset.init();
asset2.name = "ale inny";
asset2.id = 2;
asset2.save();
assertEqual( Asset.find(1).name, "taki sam, taki sam" );
asset2.destroy();
Dodawanie obsugi identyfikatorów
Obecnie za kadym razem, gdy zapisywany jest rekord, trzeba rcznie zdefiniowa jego
identyfikator ID. To przykry obowizek, ale na szczcie mona to zadanie zautomatyzowa.
Najpierw potrzebny jest jaki mechanizm generowania identyfikatorów — moe nim by ge-
nerator identyfikatorów GUID (ang. Globally Unique Identifier). Z technicznego punktu wi-
dzenia JavaScript nie moe generowa penoprawnych, 128-bitowych identyfikatorów GUID
z powodu ogranicze API, które potrafi generowa tylko liczby pseudolosowe. Generowanie
prawdziwie losowych identyfikatorów jest zawsze trudnym zadaniem i systemy operacyjne
obliczaj je na podstawie adresu MAC, pozycji myszy, sum kontrolnych BIOS-u, a nawet na
podstawie pomiarów szumu elektrycznego albo produktów rozpadu radioaktywnego; cza-
sami wrcz uywa si lamp z zawartoci cieczy oraz wosku, które po rozgrzaniu tworz
róne efekty kolorystyczne! Jednak natywna funkcja
Math.random()
, cho pseudolosowa, w zu-
penoci nam wystarczy.
Robert Kieffer napisa prosty i zwizy generator identyfikatorów GUID, który za pomoc funkcji
Math.random()
generuje GUID pseudolosowe (http://www.broofa.com/2008/09/javascript-uuid-function/).
Generator jest na tyle prosty, e moemy jego kod ródowy zaprezentowa w caoci:
Math.guid = function(){
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
}).toUpperCase();
};
Mamy wic funkcj, która generuje identyfikatory GUID, zatem zintegrowanie jej z ORM nie
nastrczy ju trudnoci. Wystarczy w tym celu zmieni kod funkcji
create()
:
Kup książkę
Poleć książkę
Adresowanie odwoa
_
53
Model.extend({
create: function(){
if ( !this.id ) this.id = Math.guid();
this.newRecord = false;
this.parent.records[this.id] = this;
}
});
Od teraz kady nowo utworzony rekord bdzie mia identyfikator w postaci losowego GUID:
ar asset = Asset.init();
asset.save();
asset.id
//=> "54E52592-313E-4F8B-869B-58D61F00DC74"
Adresowanie odwoa
Uwani Czytelnicy zapewne zwrócili uwag na bd zwizany z odwoaniami w naszej bi-
bliotece ORM. Nie klonujemy instancji ani wtedy, gdy zostaj zwrócone przez
find()
, ani
w momencie ich zapisywania, przez co jeli zmienimy któr z ich waciwoci, zmiana
dotknie oryginalnego zasobu. Jest to powany problem, poniewa oczekujemy, e zasoby
bd si zmienia jedynie po wykonaniu funkcji
update()
:
var asset = new Asset({name: "foo"});
asset.save();
// Asercja przekazuje prawidowo
assertEqual( Asset.find(asset.id).name, "foo" );
// Zmiana waciwoci bez wywoywanai update()
asset.name = "wem";
// O nie! Asercja koczy si niepowodzeniem, poniewa nazw jest teraz "wem"
assertEqual( Asset.find(asset.id).name, "foo" );
Aby wyeliminowa bd, w trakcie dziaania
find()
utworzymy nowy obiekt. Ponadto konieczne
bdzie zduplikowanie obiektu zawsze wtedy, gdy dojdzie do utworzenia lub zmiany rekordu:
Asset.extend({
find: function(id){
var record = this.records[id];
if ( !record ) throw("Rekord nieznany");
return record.dup();
}
});
Asset.include({
create: function(){
this.newRecord = false;
this.parent.records[this.id] = this.dup();
},
update: function(){
this.parent.records[this.id] = this.dup();
},
dup: function(){
return jQuery.extend(true, {}, this);
}
});
Kup książkę
Poleć książkę
54
_
Rozdzia 3. Modele i dane
Jest jeszcze jeden problem —
Model.records
to obiekt, który jest wspóuytkowany przez
wszystkie modele:
assertEqual( Asset.records, Person.records );
Daje to niepodany efekt wymieszania ze sob wszystkich rekordów:
var asset = Asset.init();
asset.save();
assert( asset in Person.records );
Rozwizanie polega na tym, by za kadym razem, gdy tworzony jest nowy model, ustawia
te nowy obiekt
records
.
Model.created()
jest wywoaniem zwrotnym do tworzenia nowego
obiektu, dlatego mona w nim ustawia dowolne obiekty dotyczce tego wanie modelu:
Model.extend({
created: function(){
this.records = {};
}
});
adowanie danych
Jeli aplikacja internetowa dziaa w jakiej czci poza przegldark, konieczne jest umoli-
wienie adowania danych zdalnie z serwera. Zazwyczaj w trakcie uruchamiania aplikacji a-
dowany jest jaki podzbiór danych, a po wykonaniu okrelonych czynnoci przez uytkow-
nika aplikacja aduje kolejne potrzebne dane. Zalenie od rodzaju aplikacji i iloci danych
komplet danych mona pozyskiwa od razu w momencie pierwszego adowania strony. Jest
to przypadek idealny, poniewa wówczas uytkownicy nie bd ju musieli czeka na zaa-
dowanie dodatkowych danych. Jednak w przypadku wikszoci aplikacji rozwizanie takie
nie wchodzi w gr, poniewa zbiór potrzebnych danych jest zbyt duy, by bez problemu
zmieci si w pamici dostpnej dla przegldarki.
Tylko dziki zaadowaniu danych od razu przy starcie aplikacji bdzie mona zapewni
uytkownikom komfort pracy z ni, a czas odpowiedzi zredukowa do minimum. Istnieje
jednak istotna rónica midzy pocztkowym adowaniem danych, które rzeczywicie s po-
tem wykorzystywane, a adowaniem danych nadmiarowych, które nigdy nie zostan uyte.
Trzeba zatem przewidzie, których danych uytkownicy bd potrzebowa, albo dokona
odpowiednich pomiarów ju w trakcie pracy aplikacji.
Na przykad jeli adowana jest lista stronicowana, to dlaczego nie zaadowa od razu za-
wartoci nastpnej strony, aby przeczanie midzy stronami nastpowao od razu? Albo,
co daoby jeszcze lepszy efekt, po prostu wywietli dug list i automatycznie adowa
i wstawia do niej dane, gdy uytkownik bdzie t list przewija (suy do tego wzorzec nie-
skoczonego suwaka). Im mniejsze bdzie opónienie widoczne dla uytkownika, tym lepiej.
Naley zapewni, e w trakcie pobierania nowych danych interfejs uytkownika nie bdzie
si blokowa. Warto wywietli jaki wskanik postpu adowania danych, ale cao interfej-
su powinna przez cay czas by dostpna dla uytkownika. Liczba sytuacji, w której bdzie
dochodzio do zablokowania interfejsu, powinna by jak najmniejsza, a najlepiej, by w ogóle
do tego nie dochodzio.
Kup książkę
Poleć książkę
adowanie danych
_
55
Dane mona wplata w definicj strony bd pobiera je w oddzielnych daniach HTTP za
pomoc Ajax lub JSONP. Polecam raczej to drugie rozwizanie, poniewa wplatanie w kod
strony duych iloci danych powoduje znaczne zwikszenie rozmiaru strony, natomiast
dziki pobieraniu danych równolegle z adowaniem strony skraca si cakowity czas jej a-
dowania. Technologie AJAX i JSONP pozwalaj dodatkowo umieszcza strony HTML w pa-
mici podrcznej, dziki czemu nie trzeba ich adowa na nowo przy kadym kolejnym
wywoaniu.
Wplatanie danych
Nie polecam stosowania tego podejcia z powodów opisanych w poprzednim akapicie, jed-
nak technika wplatania danych moe by w niektórych okolicznociach przydatna, zwaszcza
gdy adowane s niewielkie zbiory danych. Technika wplatania danych ma t niezaprzeczaln
zalet, e bardzo prosto si j implementuje.
Wystarczy w tym celu generowa obiekt JSON bezporednio w kodzie strony. W technologii
Ruby on Rails odpowiednie rozwizanie miaoby tak posta:
<script type="text/javascript">
var User = {};
User.records = <%= raw @users.to_json %>;
</script>
W przedstawionym kodzie wykorzystano znaczniki ERB, aby zwróci przetworzone przez
JSON dane uytkownika. Metoda
raw
zapobiega wstawianiu znaków ucieczki przez JSON.
W wyniku przetworzenia strony jej kod HTML bdzie wyglda tak:
<script type="text/javascript">
var User = {};
User.records = [{"first_name": "Alex"}];
</script>
JavaScript moe przetwarza dane JSON bez ich dodatkowego przeksztacania, poniewa
JSON ma tak sam struktur jak obiekty jzyka JavaScript.
adowanie danych przy uyciu Ajax
adowanie danych przy uyciu Ajax to chyba pierwsza metoda adowania zdalnych danych,
która przychodzi na myl programistom, gdy mowa o wywoaniach w tle. To nie przypadek:
technologia ta zostaa wypróbowana, przetestowana i udostpniona we wszystkich wspó-
czesnych przegldarkach. Ajax nie jest oczywicie pozbawiony wad — historia rozwoju tej
technologii, dla której nie istniay adne standardy, zakoczya si powstaniem niespójnych API.
Przez to wanie, oraz ze wzgldu na wymogi bezpieczestwa przegldarek internetowych,
adowanie danych z innych domen jest zadaniem do skomplikowanym.
Programistom, którzy potrzebuj krótkiego wprowadzenia do technologii Ajax i klasy
XMLHttpRequest
,
warto poleci artyku Getting Started w witrynie Mozilla Developer (https://developer.mozilla.org/
en/Ajax/Getting_Started). Z duym prawdopodobiestwem mona zaoy, e i tak wikszo
programistów ostatecznie wykorzysta bibliotek, na przykad jQuery, która bdzie udostpnia
warstw abstrakcji nad API Ajax i ukrywa przed programist rónice w obsudze technologii
midzy poszczególnymi przegldarkami. Dlatego w tym punkcie bdzie mowa o API biblioteki
jQuery, a nie o samej klasie
XMLHttpRequest
.
Kup książkę
Poleć książkę
56
_
Rozdzia 3. Modele i dane
API Ajax biblioteki jQuery zawiera jedn funkcj niskiego poziomu o nazwie
jQuery.ajax()
oraz kilka jej abstrakcji wyszego poziomu, dziki którym znacznie zmniejsza si ilo wy-
maganego do napisania kodu ródowego. Funkcja
jQuery.ajax()
przyjmuje midzy innymi
zbiór ustawie parametrów wywoania, typ zawartoci oraz odwoania zwrotne. W momencie
wywoania funkcji danie jest asynchronicznie wykonywane w tle.
url
Adres URL dania. Domylnym adresem URL jest adres biecej strony.
success
Funkcja, która ma zosta wywoana, gdy danie zakoczy si powodzeniem. Wszystkie
dane zwrócone przez serwer s przekazywane do funkcji jako jej parametr.
contentType
Ustawia nagówek
Content-Type
dania. Jeeli danie zawiera dane, domylnym typem
zawartoci jest
application/x-www-form-urlencoded
, które sprawdza si w wikszoci przy-
padków.
data
Dane, które naley przesa do serwera. Jeeli nie jest to cig znaków, jQuery je zseriali-
zuje i zakoduje.
type
Metoda HTTP, której naley uy do wykonania dania:
GET
,
POST
lub
DELETE
. Metod
domyln jest
GET
.
dataType
Typ danych, jakiego oczekuje si od serwera. Biblioteka jQuery wymaga podania typu
danych wynikowych, aby wiedzie, w jaki sposób je przetwarza po ich otrzymaniu. Jeeli
dataType
nie zostanie okrelony, jQuery spróbuje ten typ odgadn na podstawie typu
MIME odpowiedzi z serwera. Obsugiwane s nastpujce wartoci parametru:
text
Odpowied tekstowa, która nie wymaga adnego dodatkowego przetwarzania.
script
jQuery przyjmie, e danymi wynikowymi jest kod JavaScript, i odpowiednio te dane
przetworzy.
json
jQuery przyjmie, e danymi wynikowymi s dane JSON, i przetworzy je przy uyciu
dokadnego parsera.
jsonp
Oznacza format JSONP, który zostanie przedstawiony w dalszej czci ksiki.
Jako przykad zdefiniujemy proste danie Ajax, które wywietli dane zwrócone przez serwer:
jQuery.ajax({
url: "/ajax/endpoint",
type: "GET",
success: function(data) {
alert(data);
}
});
Kup książkę
Poleć książkę
adowanie danych
_
57
Jednak definiowanie wszystkich opcji jest do uciliwe. Na szczcie jQuery udostpnia
kilka krótszych rozwiza. Funkcja
jQuery.get()
pobiera adres URL, opcjonalne dane oraz
wywoanie zwrotne:
jQuery.get("/ajax/endpoint", function(data){
$(".ajaxResult").text(data);
});
Natomiast aby wysa kilka parametrów w ramach dania
GET
, mona to zrobi nastpujco:
jQuery.get("/ajax/endpoint", {foo: "bar"}, function(data){
/* ... */
});
Jeeli spodziewamy si, e serwer zwróci dane JSON, trzeba uy funkcji
jQuery.getJSON()
,
która automatycznie ustawia opcj
dataType
dania na
"json"
:
jQuery.getJSON("/json/endpoint", function(json){
/* ... */
});
Dostpna jest analogiczna funkcja
jQuery.post()
, która równie przyjmuje adres URL, dane
i wywoanie zwrotne:
jQuery.post("/users", {first_name: "Alex"}, function(result){
/* danie POST Ajax zakoczyo si powodzeniem */
});
Aby skorzysta z innych metod HTTP, czyli
DELETE
,
HEAD
i
OPTIONS
, trzeba uy niskopoziomowej
funkcji
jQuery.ajax()
.
W tym punkcie przedstawiono krótki opis API Ajax biblioteki jQuery. Wicej informacji na
ten temat mona znale w kompletnej dokumentacji dostpnej na stronie pod adresem
http://api.jquery.com/category/ajax.
Istotnym ograniczeniem Ajax jest obowizujca w tej technologii zasada tosamego pocho-
dzenia
(ang. same origin policy), która ogranicza moliwo obsugi tylko do da o tej samej
domenie, subdomenie i tym samym porcie, co adres strony, która danie wykonuje. Jest po
temu istotna przyczyna: otó zawsze, gdy wysyane jest danie Ajax, wraz z nim wysyane
s wszystkie dane cookie domeny. Dla serwera zdalnego jest to znak, e danie pochodzi od
zalogowanego uytkownika. Gdyby nie obowizywaa zasada tosamego pochodzenia, po-
tencjalny napastnik mógby pobra wszystkie wiadomoci pocztowe innej osoby z jej skrzynki
Gmail, zmienia statusy na czyim profilu Facebooka albo publikowa wiadomoci w czyim
imieniu na Twitterze — jednym sowem, byoby to istotne zagroenie bezpieczestwa.
Jednak zasada tosamego pochodzenia, która jest istotnym elementem systemu bezpiecze-
stwa w sieci WWW, nakada na programistów bardzo niewygodne ograniczenia, poniewa
odbiera im moliwo korzystania z w peni bezpiecznych zasobów zdalnych. Inne technologie,
na przykad Adobe Flash i Java, udostpniaj obejcia tego problemu w postaci plików z re-
guami dostpu do innych domen. Do tego towarzystwa doczy ostatnio Ajax wraz ze swoim
standardem o nazwie CORS (http://www.w3.org/TR/access-control), wyznaczajcym zasady wspó-
uytkowania zasobów midzy domenami.
Dziki CORS mona wyama si z zasady tosamego pochodzenia i uzyska dostp do au-
toryzowanych, zdalnych serwerów. Specyfikacja standardu CORS zostaa zaimplementowana
w najwaniejszych przegldarkach, dlatego jeli tylko nie jest uywana przegldarka IE6, nie
powinno by z tym standardem wikszych problemów.
Kup książkę
Poleć książkę
58
_
Rozdzia 3. Modele i dane
Zakres obsugi standardu CORS w poszczególnych przegldarkach opisano poniej:
x
IE >= 8 (z pewnymi ograniczeniami).
x
Firefox >= 3.
x
Safari: pena obsuga.
x
Chrome: pena obsuga.
x
Opera: brak obsugi.
Korzystanie z CORS nie sprawia adnych problemów. Aby autoryzowa dostp do wasnego
serwera, wystarczy do nagówka zwracanych odpowiedzi dodawa te dwa wiersze:
Access-Control-Allow-Origin: przyklad.com
Access-Control-Request-Method: GET,POST
Powyszy nagówek autoryzuje dania
GET
i
POST
do innej domeny wykonywane z domeny
przyklad.com. Gdy wartoci jest wicej ni jedna, naley oddzieli je od siebie przecinkami,
tak samo jak w przypadku metod
GET
,
POST
powyej. Aby umoliwi dostp z wicej ni
jednej domeny, wystarczy zawrze ich list oddzielon od siebie przecinkami w nagówku
Access-Control-Allow-Origin
. Natomiast aby zezwoli na dostp z dowolnej domeny, naley
w nagówku
Origin
wpisa znak gwiazdki (
*
).
Niektóre przegldarki, na przykad Safari, najpierw wykonuj danie
OPTIONS
, aby spraw-
dzi, czy kolejne danie bdzie dozwolone. Z kolei Firefox przele od razu waciwe danie
i dopiero w przypadku braku nagówków CORS rzuci wyjtek. W trakcie implementowania
kodu ródowego trzeba wzi pod uwag te rónice w dziaaniu serwerów.
Standard CORS pozwala nawet na autoryzowanie da z niestandardowymi nagówkami.
Suy do tego nagówek
Access-Control-Request-Headers
:
Access-Control-Request-Headers: Authorization
Tak skonstruowany nagówek oznacza, e klienty mog dodawa wasne nagówki do da
Ajax i na przykad podpisywa dania za pomoc OAuth:
var req = new XMLHttpRequest();
req.open("POST", "/endpoint", true);
req.setRequestHeader("Authorization", oauth_signature);
Niestety, mimo e standard CORS jest obsugiwany w Internet Explorerze 8 i jego nowszych wer-
sjach, Microsoft zignorowa specyfikacj standardu i grup robocz (http://lists.w3.org/Archives/
Public/public-webapps/2008AprJun/0168.html) i utworzy wasny obiekt
XDomainRequest
(http://msdn.
microsoft.com/en-us/library/cc288060%28VS.85%29.aspx), którym w przypadku da midzy
domenami naley zastpi obiekt
XMLHttpRequest
. Obiekt
XDomainRequest
ma interfejs podobny
do interfejsu obiektu
XMLHttpRequest
, jednak zdefiniowano dla niego wiele dodatkowych ograni-
cze i restrykcji (http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-
limitations-and-workarounds.aspx). Na przykad obiekt obsuguje tylko metody
GET
i
POST
, nie s
obsugiwane nagówki uwierzytelniania ani nagówki niestandardowe, a w kocu — i to
jest najdziwniejsze — sporód typów zawartoci obsugiwany jest wycznie
Content-Type:
text/plain
. Zatem aby skorzysta z CORS w IE, trzeba — oprócz uycia prawidowych na-
gówków
Access-Control
— opracowa odpowiednie obejcia dla wspomnianych przed chwil
ogranicze.
Kup książkę
Poleć książkę
adowanie danych
_
59
JSONP
JSONP (http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp), albo inaczej JSON z wy-
penianiem, to technologia opracowana przed zdefiniowaniem standardu CORS. JSONP sta-
nowi kolejne narzdzie do pobierania danych ze zdalnych serwerów. Mechanizm dziaania
JSONP polega na tym, e definiowany jest znacznik skryptu, który wskazuje na kocówk
JSONP. Tam wanie zwracane dane s opakowywane w wywoanie funkcji. Znaczniki skryp-
tów nie podlegaj ograniczeniom zwizanym z komunikacj midzy domenami, a poza tym
opisywana technika jest obsugiwana waciwie przez kad przegldark.
Poniej przedstawiono znacznik skryptu, który wskazuje na zdalny serwer:
<script src="http://przyklad.com/dane.json"> </script>
Kocówka dane.json zwraca obiekt JSON opakowany w wywoanie funkcji:
jsonCallback({"data": "foo"})
Nastpnie definiuje si funkcj dostpn globalnie. Gdy tylko skrypt zostanie zaadowany,
nastpi wywoanie tej funkcji:
window.jsonCallback = function(result){
// Przetwarzanie danych wynikowych
}
Jak wida, proces jest do zawiy. Na szczcie jQuery udostpnia o wiele bardziej zwize
API do niego:
jQuery.getJSON("http://przyklad.com/dane.json?callback=?", function(result){
// Przetwarzanie danych wynikowych
});
Biblioteka jQuery zastpi ostatni znak zapytania w powyszym adresie URL losow nazw
utworzonej tymczasowej funkcji. Serwer bdzie musia natomiast odczytywa parametr
callback
i uywa go w roli nazwy zwracanej funkcji opakowujcej.
Bezpieczestwo da midzy domenami
Jeeli posiadany serwer jest udostpniany dla da JSONP z rónych domen, trzeba do-
gbnie przemyle kwesti jego zabezpieczenia. Zazwyczaj zasada wspóuytkowania zaso-
bów midzy domenami uniemoliwia potencjalnemu napastnikowi na przykad wywoanie
API Twittera i pobranie osobistych danych innych uytkowników. Wszystko zmienia si jed-
nak w przypadku zastosowania CORS i JSONP. Podobnie jak w przypadku zwykego dania
Ajax, wszystkie cookie sesji s przekazywane w ramach dania, co oznacza, e zalogowanie
do API Twittera ju si dokonao. Potencjalny napastnik bdzie wic móg przej pen
kontrol nad kontem, a to przesdza spraw — bezpieczestwo wymaga najwyszej uwagi.
Jeeli zatem nie mona z góry ograniczy zbioru domen, które bd korzysta z API i planuje
si uy technologii CORS/JSONP, naley zastosowa si do nastpujcych wytycznych:
x
Nie naley ujawnia adnych poufnych danych, takich jak adresy poczty elektronicznej.
x
Nie mona zezwala na wywoanie jakichkolwiek akcji (jak na przykad „follow” na
Twitterze).
Aby zapewni odpowiedni poziom bezpieczestwa, mona take z góry wyznaczy okrelone
domeny, które bd mogy korzysta z API, lub uy uwierzytelnienia OAuth.
Kup książkę
Poleć książkę
60
_
Rozdzia 3. Modele i dane
Wypenienie ORM danymi
Wypenienie biblioteki ORM odpowiednimi danymi jest bardzo prostym zadaniem. Wystar-
czy pobra dane z serwera, po czym uaktualni rekordy modelu. Dodamy zatem funkcj
populate()
do obiektu
Model
. Funkcja
populate()
bdzie iterowa przez kolejne przekazane do
niej wartoci oraz tworzy instancje i uaktualnia obiekty
records
:
Model.extend({
populate: function(values){
// Reset modelu i obiektu records
this.records = {};
for (var i=0, il = values.length; i < il; i++) {
var record = this.init(values[i]);
record.newRecord = false;
this.records[record.id] = record;
}
}
});
Teraz mona ju uy funkcji
Model.populate()
wraz z wynikiem dania, które pobiera dane:
jQuery.getJSON("/assets", function(result){
Asset.populate(result);
});
W ten sposób wszystkie dane zwrócone przez serwer stan si dostpne w bibliotece ORM.
Przechowywanie danych lokalnie
W przeszoci przechowywanie danych na lokalnym komputerze byo ogromnym wyzwa-
niem. Jedynym dostpnym rozwizaniem byo wykorzystanie plików cookie oraz moduów
rozszerzajcych, takich jak Adobe Flash. Cookie maj przestarzae API, nie mog przecho-
wywa zbyt duej iloci danych, a wszystkie znajdujce si w nich dane s przesyane do
serwera wraz z kadym daniem, co niepotrzebnie zwiksza transfer. Jeli za chodzi o Flash,
wystarczy powiedzie, e najlepiej trzyma si z dala od wszystkich moduów rozszerzajcych.
Na szczcie mechanizm przechowywania danych lokalnie zawarto w specyfikacji HTML5
i jest on obsugiwany przez wikszo wspóczesnych przegldarek. W odrónieniu od cookies
dane s w tym przypadku przechowywane wycznie po stronie klienta i nigdy nie s prze-
syane na serwery. Ilo danych, które mona w ten sposób przechowywa, jest take niepo-
równanie wiksza, a maksymalny dozwolony wolumen zaley od przegldarki (oraz jej wersji,
zgodnie z list poniej); nigdy jednak wolumen ten nie jest mniejszy ni 5 MB na domen:
x
IE >= 8.
x
Firefox >= 3.5.
x
Safari >= 4.
x
Chrome >= 4.
x
Opera >= 10.6.
Mechanizm przechowywania danych zosta opisany w specyfikacji Web Storage HTML5
(http://www.w3.org/TR/webstorage) i skada si z dwóch elementów: przechowywania lokalnie
(ang. local storage) oraz przechowywania w sesji (ang. session storage). Dane przechowywane
Kup książkę
Poleć książkę
Dodanie mechanizmu przechowywania danych lokalnie do ORM
_
61
lokalnie zostaj utrzymane równie po zamkniciu przegldarki, natomiast dane przecho-
wywane w sesji s dostpne wycznie do czasu zamknicia okna. Wszystkie dane s prze-
chowywane w kontekcie ich domeny i udostpniane wycznie tym skryptom, które pocho-
dz z domen stanowicych ródo tych danych.
Aby skorzysta z mechanizmów przechowywania danych lokalnie i przechowywania danych
w sesji, naley uy odpowiednio obiektu
localStorage
oraz
sessionStorage
. Odpowiednie API
jest bardzo podobne do w dziaaniu do mechanizmu ustawiania waciwoci na obiektach
JavaScriptu i, jeli nie liczy rónic w nazwach obydwóch wspomnianych obiektów, jest iden-
tyczne dla obydwóch mechanizmów:
// Ustawienie wartoci
localStorage["someData"] = "wem";
API WebStorage udostpnia jeszcze kilka innych funkcji:
// Liczba przechowywanych elementów danych
var itemsStored = localStorage.length;
// Ustawienie danych
localStorage.setItem("someData", "wem");
// Pobranie danych, zwrócenie null, jeli dane s nieznane
localStorage.getItem("someData"); //=> "wem";
// Usunicie danych, zwrócenie null, jeli dane s nieznane
localStorage.removeItem("someData");
// Wyczyszczenie wszystkich elementów danych
localStorage.clear();
Dane s przechowywane w postaci cigów znaków, dlatego jeli konieczne bdzie zapisanie
obiektów albo liczb cakowitych, trzeba bdzie samodzielnie dokona odpowiednich prze-
ksztace. Aby to zrobi przy uyciu JSON, naley zserializowa obiekty do postaci JSON
przed ich zapisaniem, natomiast w przypadku odczytywania obiektów — zdeserializowa
cigi znaków JSON:
var object = {some: "object"};
// Serializacja i zapisanie obiektu
localStorage.setItem("seriData", JSON.stringify(object));
// Zaadowanie i deserializacja obiektu
var result = JSON.parse(localStorage.getItem("seriData"));
Jeeli wolumen danych przekroczy dozwolony rozmiar (zwykle jest to 5 MB na jeden serwer ró-
dowy), w momencie próby zapisania kolejnych danych zwrócony zostanie bd
QUOTA_EXCEEDED_ERR
.
Dodanie mechanizmu
przechowywania danych lokalnie do ORM
Dodajmy do biblioteki ORM opcj przechowywania danych na lokalnym komputerze, aby
umoliwi utrzymanie rekordów midzy kolejnymi odwieeniami strony. Aby skorzysta
z obiektu localStorage, naley zserializowa rekordy do postaci cigu znaków JSON. Problem
polega na tym, e obecnie zserializowane obiekty wygldaj nastpujco:
var json = JSON.stringify(Asset.init({name: "foo"}));
json //=> "{"parent":{"parent":{"prototype":{}},"records":[]},"name":"foo"}"
Kup książkę
Poleć książkę
62
_
Rozdzia 3. Modele i dane
Trzeba wic pokry mechanizm serializacji JSON dla naszych modeli. W tym celu najpierw
ustalmy, które waciwoci trzeba zserializowa. Do obiektu
Model
dodamy tablic
attributes
,
w której kady z modeli bdzie wskazywa odpowiednie atrybuty przeznaczone do serializacji:
Model.extend({
created: function(){
this.records = {};
this.attributes = [];
}
});
Asset.attributes = ["name", "ext"];
Poniewa kady model ma odmienne atrybuty, przez co modele nie mog wspóuytkowa
tej samej tablicy
attributes
, waciwoci tej nie ustawia si bezporednio na obiekcie
Model
.
Zamiast tego nowa tablica jest tworzona w momencie tworzenia modelu — analogicznie jak
w przypadku obiektu
records
.
Utworzymy teraz funkcj
attributes()
, która zwróci obiekt dla atrybutów i wartoci:
Model.include({
attributes: function(){
var result = {};
for(var i in this.parent.attributes) {
var attr = this.parent.attributes[i];
result[attr] = this[attr];
}
result.id = this.id;
return result;
}
});
Dla kadego modelu mona ju zdefiniowa tablic atrybutów:
Asset.attributes = ["name", "ext"];
Wówczas funkcja
attributes()
bdzie zwraca obiekt z odpowiednimi waciwociami:
var asset = Asset.init({name: "document", ext: ".txt"});
asset.attributes();
//=> {name: "document", ext: ".txt"};
Aby pokry funkcj
JSON.stringify()
, wystarczy wykona metod
toJSON()
na instancjach
modeli. Biblioteka JSON wyszuka za pomoc tej funkcji obiekt przeznaczony do zserializo-
wania, zamiast zserializowa obiekt
records
w jego obecnej postaci:
Model.include({
toJSON: function(){
return(this.attributes());
}
});
Spróbujmy teraz ponownie zserializowa rekordy. Tym razem wynikowy cig znaków JSON
bdzie zawiera prawidowe waciwoci:
var json = JSON.stringify(Asset.records);
json //= "{"7B2A9E8D...":"{"name":"document","ext":".txt","id":"7B2A9E8D..."}"}"
Skoro serializacja JSON dziaa bez zarzutu, dodanie obsugi przechowywania danych lokal-
nie do naszego modelu bdzie trywialne. Do obiektu
Model
dodamy w tym celu dwie funkcje:
saveLocal()
oraz
loadLocal()
. W trakcie zapisywania obiekt
Model.records
zostanie przekszta-
cony w tablic, zserializowany i wysany do
localStorage
:
var Model.LocalStorage = {
saveLocal: function(name){
// Przeksztacenie records w tablic
var result = [];
Kup książkę
Poleć książkę
Przesyanie nowych rekordów na serwer
_
63
for (var i in this.records)
result.push(this.records[i])
localStorage[name] = JSON.stringify(result);
},
loadLocal: function(name){
var result = JSON.parse(localStorage[name]);
this.populate(result);
}
};
Asset.extend(Model.LocalStorage);
Zapewne dobrym pomysem bdzie odczytywanie rekordów z lokalnego repozytorium
w trakcie adowania strony i ich zapisywanie, gdy strona bdzie zamykana. Zostawiam to
jednak jako wiczenie dla Czytelników.
Przesyanie nowych rekordów na serwer
Nieco wczeniej w tej ksice pokazano, jak wykorzystywa funkcj
post()
biblioteki jQuery,
aby przesya dane do serwera. Funkcja przyjmuje trzy argumenty: docelowy adres URL,
dane dania i wywoanie zwrotne:
jQuery.post("/users", {first_name: "Alex"}, function(result){
/* danie POST Ajax zakoczyo sie powodzeniem */
});
Dziki wczeniejszemu zaimplementowaniu funkcji
attributes()
tworzenie rekordów na ser-
werze jest ju proste — wystarczy metod
POST
przesa atrybuty rekordu:
jQuery.post("/assets", asset.attributes(), function(result){
/* danie POST Ajax zakoczyo sie powodzeniem */
});
Aby konsekwentnie trzyma si konwencji REST, w momencie tworzenia rekordu naley
wykonywa danie HTTP
POST
, za w chwili zmiany tego rekordu — danie HTTP
PUT
.
Dodajmy zatem do instancji
Model
dwie funkcje o nazwach
createRemote()
i
updateRemote()
,
które bd odpowiada za wysanie do serwera dania HTTP odpowiedniego rodzaju:
Model.include({
createRemote: function(url, callback){
$.post(url, this.attributes(), callback);
},
updateRemote: function(url, callback){
$.ajax({
url: url,
data: this.attributes(),
success: callback,
type: "PUT"
});
}
});
Teraz, jeli na instancji zasobu
Asset
zostaje wywoana funkcja
createRemote()
, atrybuty in-
stancji s przesyane do serwera metod
POST
:
// Sposób uycia:
Asset.init({name: "jason.txt"}).createRemote("/assets");
Kup książkę
Poleć książkę
64
_
Rozdzia 3. Modele i dane
Kup książkę
Poleć książkę
255
Skorowidz
A
Adobe Flash, 116
Ajax, 226
Ajax Crawling, 77
akcje szablonowe, 217
alias $, 221, 227
alias fn, 23
Alman Ben, 44
AMD, Asynchronous Module Definition, 93
analiza
DOM, 140
CSS, 140
wydajnoci sieci WWW, 156
da sieciowych, 144
anulowanie zdarze, 101
API, 33
Ajax, 226
biblioteki jQuery, 39, 55, 221
biblioteki Spine, 171
do obsugi plików, 97
History, 79, 80
History HTML5, 78
Socket.IO, 119
WebSocket, 119
aplikacja
Less.app, 234
Holla, 15, 120
architektura aplikacji, 18, 47
arkusze stylów Less, 234
asercje, 125
atrybut, 180, 203
data-main, 94
defer, 150
files, 99
multiple, 98
audyt strony internetowej, 155
audytory, 155
automat skoczony, 74
automatyczna aktualizacja widoku, 88
B
Backbone, 179
aplikacja, 192
delegowanie zdarze, 184
kolekcje, 181
komunikacja z serwerem, 188
kontrolery, 186
modele, 180
obsuga historii, 187
wizanie, 185
widoki, 183
barwa, hue, 236
bezpieczestwo, 98, 115
bezpieczestwo da, 59
biblioteka
Backbone, 179
Controller, 73
Envjs, 134
gem Ruby-YUI-compressor, 153
Growl, 228
Ichabod, 136
Jammit, 153
JavaScriptMVC, 199
jQuery, 15, 32, 221
jQuery UI, 228
jQuery.tmpl, 83, 86, 195
Less, 231
Less.js, 234
Modernizr, 248
ORM, 60
Prototype, 33
QUnit, 126
Rhino, 90
Selenium, 132
Socket.IO, 118
SpiderMonkey, 90
Spine, 33, 157
Sprocket, 153
Kup książkę
Poleć książkę
256
_ Skorowidz
biblioteka
Sprockets, 95
Super.js, 27
Watir, 131
Vows.js, 135
YUI Compressor, 153
YSlow, 155
Zepto.js, 179
Zombie.js, 134
biblioteki
asercji, 126
adowania moduów, 92
odwzorowa obiektowo-relacyjnych, 48
pomocnicze, 20
powiadomie, 228
szablonów, 83
testujce, 129
zdarze, 39
bdy aplikacji, 142
C
CDN, Content Delivery Network, 92, 154
cieniowanie, 238
Comet, 113
CommonJS, 90
CORS, 57
CRUD, Create, Read, Update, Delete, 188
CSS, 231
rozszerzenia, 231
CSS3, 232, 235, 250
czas wykonania kodu, 147
czat, 120
czcionki, 246
D
Dangoor Kevin, 90
data wyganicia zasobu, 151
debugger JavaScriptu, 140, 143
definiowanie cieni, 238
deklarowanie moduu, 90
delegowanie, 29
delegowanie zdarze, 40, 72, 168, 184
dugotrwae poczenie, long polling, 113
dodawanie
dziedziczenia, 26
funkcji, 23
funkcji prywatnych, 31
kontekstu, 67
metod, 24
przezroczystoci, 237
waciwoci, 24
waciwoci instancji, 33
waciwoci klasy, 33
dokumentacja jQuery, 225
dokumentacja LABjs, 96
DOM, 39
domenowy jzyk skryptowy DSL, 132
dostp do plików, 97, 99
dostp do widoków, 70
DRY, Don’t Repeat Yourself, 69
duszki CSS, CSS sprites, 149
dynamiczna wersja strony, 78
dziedziczenie, 26
dziedziczenie klas, 25
dziedziczenie statyczne, 201
E
ECMAScript, 17
eksport przypadków testowych, 133
elegancka degradacja, graceful degradation, 235, 247
element Socket.IO, 119
enkapsulacja usug, 207
Envjs, 134
ES5, 30
etykietowanie elementu, 219
F
Firebug, 140
format JSON, 116
formularz form, 108
FSM, Finite State Machine, 74
FUBC, 96
funkcja
$$(), 142
$(), 142
$x(), 142
activate(), 75
add(), 74
addChange(), 87
addClass(), 224
addElement(element, x, y), 101
addEventListener(), 35, 40
listener, 35
type, 35
useCapture, 35
ajax(), 226
App.log(), 142
append(), 223
apply(), 27
assert(), 14, 125
assertEqual(), 14
attributes(), 63, 162
autoLink(), 84
Kup książkę
Poleć książkę
Skorowidz
_ 257
Backbone.sync(), 188, 190
method, 191
model, 191
options, 191
bind(), 30, 39, 45, 225
call(), 27
change(), 87
clear(), 142
close(), 116
comparator(), 183
confirm(), 37
console.log(), 141, 144
console.profile(), 146
console.profileEnd(), 146
contextFunction(), 67
create(), 50
created(), 159
createRemote(), 63
deactivate(), 75
delegate(), 40, 42
delegateEvents(), 72
destroy(), 48
dir(), 142
document.createElement(), 81
eval(), 91
extend(), 25, 45
fetch(), 189
find(), 52
getData(), 104
getJSON(), 226
history.pushState(), 79
html(), 224
include(), 25, 68
init(), 50, 71
inspect(), 143
jQuery.ajax(), 56, 57
jquery.makeArray(), 29
jQuery.post(), 57
jQuery.proxy(), 29, 226
jQuery.tmpl(), 83
keys(), 143
loadLocal(), 62
Math.random(), 52
module(), 127
Object.create(), 49
populate(), 60
post(), 63
prepend(), 223
preventDefault(), 37
proxy(), 29, 40, 68
publish(), 45
ready(), 39
refresh(), 189
refreshElements(), 72, 168
removeEventListener(), 35
render(), 184
require(), 90, 93
route(), 187
saveLocal(), 62
saveLocation(), 187
send(), 108, 115
setData(), 100
setDragImage(), 101
slice(), 106
stopImmediatePropagation(), 37
stopPropagation(), 37
subscribe(), 45
template(), 175
test(), 127
text(), 225
toggleClass(), 69
toJSON(), 184
trigger(), 41, 161
update(), 53
uploadFile(), 111
validate(), 164, 181
values(), 143
funkcje
anonimowe, 31
konstruktora, 22
obsugi szablonów, 84
pomocnicze aplikacji, 84
pomocnicze konsoli, 142
porównujce, 130
G
generator identyfikatorów GUID, 52
generowanie obiektu JSON, 55
generowanie widoku, 81, 184
Go, 119
Google Chrome Frame (GCF), 249
gradienty, 239, 251
GUID, Globally Unique Identifier, 52
Gzip, 153
H
hash value, 76, 79
historia przegldarki, 79
HJS, 32
Holla, 15, 120
HTML5, 97
I
Ichabod, 136
identyfikator ID, 52
implementowanie sterownika, 131
Kup książkę
Poleć książkę
258
_ Skorowidz
informacje o pliku, 101, 109
inkapsulacja zasigu, 21
inspektory, 138
instalacja Spine, 157
interfejs kanaowy, 119
interoperacyjno kodu, 90
iteracje, 84
iterator
each(), 223
map(), 223
J
Jasmine, 129
jasno, lightness, 236
JavaScriptMVC, 199
$.Class, 199
$.Controller, 199
$.Model, 199
$.View, 199
kontrolery, 213
metoda bazowa, 201
modele, 203, 205
obsuga szablonów, 211, 213
tworzenie klasy, 200
jQuery
nextPrev, 204
JSMin, 153
JSON, 207
Juggernaut, 119
K
kana alfa, 236
kana RSS, 120
kaskadowe arkusze stylów, 231
klasa
$.Class, 200
$.Controller, 200, 215
$.Model, 207
$.View, 210, 212
active, 41
Backbone.Controllers, 186
Class, 202
Clicky, 201
Controller, 69
foo, 221
nagówków, 151
no-js, 248
potomna, 26
selected, 221
Spine.List, 174
WebSockets, 115
kolejno elementów, 183
kolekcje, 182
kolory, 236
kompilacja Less, 233, 234
kompresja Gzip, 153
komunikacja z serwerem, 188
konfiguracja JavaScriptMVC, 200
konsola, 141
konstruktor jQuery, 223
konteksty, 28, 134, 160
kontroler, 21, 166, 186, 213
aplikacji, 65
App, 178
Contacts, 175
Sidebar, 173
kontrolka do przesyania plików, 98
kontrolki stronicowania
count, 203
limit, 203
offset, 203
kontrolowanie zasigu, 30
konwencja REST, 63
kopiowanie, 103
L
LABjs, 96
Less.app, 234
liczba da HTTP, 149
lista dozwolonych domen klientów, 117
lista mechanizmów transportowych, 118
lista zada, 218
logika prezentacji, 20
adowanie
danych, 54, 55
moduu, 92
plików na serwer, 107
równolege, 96
synchroniczne moduów, 91
szablonów, 85
widoku, 212
acuchy wywoa, 227
czenie moduów, 95
M
manipulowanie modelem DOM, 223
maszyna stanów, 45, 74
metoda
alert(), 138
DELETE, 207
GET, 207
Kup książkę
Poleć książkę
Skorowidz
_ 259
multipart/form-data, 109
POST, 207
PUT, 207
toJSON(), 62
metody pomocnicze, 206
migawki, 147
minifikacja, 95, 152
model, 19
Contact, 173
danych kontaktowych, 173
DOM, 223
elastycznych kontenerów, 245
Paginate, 205
wartoci domylne, 206
Task, 207
modele, 161, 180, 203
modu, 25
Adobe Flash, 60
application, 92
CommonJS, 92
HJS, 32
maths.js, 91
mod_deflate, 154
nextPrev, 204
Spine.Events, 161
utils, 93
V8 JS, 118
Web Inspector, 136
moduy, 89
modyfikatory jQuery, 211
MVC, Model View Controller, 18, 85, 180
N
nagówek
Expires, 150
Last-Modified, 152
protokou HTTP, 114
nagrywanie sesji, 132
narzdzie
Fetch as Googlebot, 78
Firebug, 140, 155
Firebug Lite, 141
Juggernaut, 119
LABjs, 96
MooTools, 39
Prototype, 39
Pusher, 119
rack-modulr, 95
Selenium IDE, 132
TestSwarm, 137
Web Inspector, 138
YUI, 39
narzdzie do przesyania plików, 98
nasuch zdarzenia click, 21
nasuchiwanie zdarze, 218
nasycenie, saturation, 236
natywna implementacja klas, 22
natywna obsuga klas, 32
natywny inspektor kodu, 140
nazwy funkcji konstruktorów, 22
negacja selektorów, 242
negocjowanie pocze TCP, 114
Node.js, 118
O
obiekt
Asset, 45
Blob, 106
clipboardData, 103
Controller, 68
dataTransfer, 102
elements, 72
event, 36, 37
Events, 72, 74
exports, 68
File
name, 98
size, 98
type, 98
FileList, 98
FileReader, 105
FormData, 108
localStorage, 61
Model, 49
prototypowy, 26
rpc, 116
sessionStorage, 61
User, 48
obiekty wstrzymane, deferred objects, 212
obserwatory zdarze, 115
obsuga
IE6, 235
moduów, 25
przecigania, 100
przej, 242
szablonów, 211
szablonów HTML, 195
wywoa zwrotnych, 25
zdarze, 161
obszar upuszczania, 111
odpytywanie cige serwera, 113
opakowywanie moduów, 94
opcje nagówka, 151
max-age, 151
must-revalidate, 151
Kup książkę
Poleć książkę
260
_ Skorowidz
no-store, 151
public, 151
operator
new, 22
not, 242
this, 225
var, 31
ORM, 45, 48, 52
P
pami podrczna, 150
pasek postpu, 109
platforma programistyczna JS, 199
platforma Rack, 233
plik
application.rb, 233
helpers.js, 84
production.rb, 234
spine.model.local.js, 164
pliki cookie, 60
pliki PSD, 235
polecenie rackup, 95
poczenia wss, 117
poczenie zdublowane, 115
prdko dziaania, 121
prdko generowania stron, 156
proces JuggernautObserver, 120
profilowanie kodu, 146
protokó WebSocket, 117
prototyp
Function, 31
Object.prototype, 26
prototype, 23
przechowywanie
danych, 60
lokalne, local storage, 60
stanu na kliencie, 65
szablonów, 85
w sesji, session storage, 60
przeciganie, 100
plików poza przegldark, 101
tekstu, 100
przedrostki stylów, 236
przegldarka
Chrome, 123, 235
Firefox, 123, 235
IE, 123, 235
Opera, 123
Safari, 123, 235
przejcia, 242
przekierowanie
robota, 78
stae, 78
tymczasowe, 78
przepyw zdarze, 19
przestrze nazw, 20, 89
przesyanie plików, 108, 111
przetwarzanie plików, 97
przezroczysto, 236
punkt przerwania, 143
Pusher, 119
Q
QUnit, 126
R
Rack, 119
Rack and Rails, 96
reguy zagniedone, 232
rekomendacje, 155
rekordy, 162, 163
repozytorium GitHub, 15
RequireJS, 93
Resig John, 33
REST, Representational State Transfer, 189, 207
robot, 78
rozmiar dania, 114
rozszerzanie klas, 159
rozszerzanie modeli, 205
rozszerzenia jQuery, 227
RPC, Remote Procedure Call, 116
Ruby, 25
S
selektor nth-child, 241
selektory, 221, 241
Selenium IDE, 132
serwer zdarzeniowy, 118
serwis Quirksmode, 36
sie dostarczania treci, 154
silnik generowania stron WWW, 235
silnik WebKit, 103
skadnia stylów CSS3, 254
sowo kluczowe
class, 23
new, 23
this, 23, 67
Socket.IO, 118
specyfikacja
Ajax Crawling, 78
JavaScript, 30
Web Storage, 60
Spine, 32, 157
aplikacja, 172, 178
delegowanie zdarze, 168
klasy, 158
Kup książkę
Poleć książkę
Skorowidz
_ 261
kontrolery, 166
modele, 161
proxied, 167
waciwo elements, 167
zapisywanie, 164
zdarzenia, 161
zdarzenia standardowe, 163
Sprockets, 95
stan aplikacji, 76
stan strony, 65
standard CORS, 58
sterowniki, drivers, 131
stronicowanie, 203
styl
@font-face, 246
border-image, 244
border-radius, 237
box-shadow, 238
box-sizing, 244
hsl, 236
rgb, 236
text-shadow, 239
style gradientów CSS3, 236
style standardowe, 235
subszablony, 212
szablony, 82
EJS, 211
JAML, 211
adowanie wstpne, 213
Micro, 211
pakowanie, 213
Tmpl, 211
rodowisko testowe, 126
T
tabela zgodnoci zdarze, 36
tablica
asocjacyjna atrybutów, 180
asocjacyjna zdarze, 184
attributes, 62
nazw atrybutów, 161
nazw funkcji, 167
technologia
AJAX, 55
JSONP, 55, 59
Rails, 120
Ruby, 95
testowanie
kodu, 123
niezalene, 134
rozproszone, 137
testy
Jasmine, 131
JavaScript, 131
jednostkowe, 125
QUnit, 128
to, 241
tooltip, 215
Tornado, 119
transformacje, 244
Transport C, 92
Transport D, 92
tworzenie
asercji, 130
biblioteki Growl, 228
gniazdka, 115
graficznych interfejsów uytkownika, 245
instancji, 22, 158, 200
instancji kontrolera, 216
instancji modelu na serwerze, 208
klas, 22
klasy, 200
kolekcji, 182
kontrolerów, 65, 70, 186
modeli, 180
ORM, 48
rekordów na serwerze, 63
statycznych szablonów, 235
ukadu, 250
widoków, 81
widetów, 219
typ
atrybutów, 209
MIME, 56
zwracanych danych, 105
typy zdarze, 37
U
ukrywanie zakadek, 42
upuszczanie, 101
usuga REST, 207
ustawianie wartoci, setters, 205
utrzymywanie rekordów, 51
W
W3C, 35
warstwa abstrakcji, 121, 180
warstwa abstrakcji dla zdarzenia, 100
Watir, 131
wczytywanie pliku, 105
wdraenie aplikacji internetowej, 149
Web Inspector, 138, 145
WebKit, 235
Kup książkę
Poleć książkę
262
_ Skorowidz
WebSockets, 114
Web-sockets-js, 116
weryfikacja poprawnoci, 164
wiadomoci Message, 120
wizanie, 86
modeli, 87
zdarze, 216
widok, 20
AppView, 195
TodoView, 195
widoki, 183
widet
dymku z porad, 214
listy, 215
nextPrev, 214
witryna Mozilla Developer, 55
wklejanie, 104
wasne
przyciski przegldarki, 107
wywoanie zwrotne, 86
zdarzenia, 168
znaczniki skryptów, 85
wasny protokó, 116
waciwoci, 24
ORM, 50
zdarze, 38
waciwo elements, 167
wplatanie danych, 55
wplecenia, 232
wyciekanie pamici, 214
wydajno aplikacji, 90, 94, 114, 149
wydzielanie biblioteki, 68
wykrywanie WebSockets, 115
wypenianie kolekcji, 189
wywoanie zwrotne, 45
wywoywanie funkcji, 27
wywoywanie metody bazowej, 201
wzorzec
Element, 170
Module, 228
moduu, 66
MVC, 47, 180
Publish/Subscribe, 43
PubSub, 119, 120
Render, 170
X
XHR, 92
XMLHttpRequest, 108, 226
Y
Yabble, 92
Z
zadanie CRUD
pobieranie, 208
tworzenie, 208
uaktualnianie, 209
usuwanie, 209
zamykanie poczenia, 116
zarzdzanie
oczekiwaniami, expectation management, 122
zalenociami, 89, 96
zdarzeniami, 39
zasada tosamego pochodzenia, 57
zasig klasy, 29
zasig kontekstu, 67
zdarzenia
anulowanie, 37
CRUD, 210
delegowanie, 40
globalne, 169
kontrolera, 168
modelu, 163
nasuchiwanie, 35
przechodzce w dó, event capturing, 36
przechodzce w gór, event bubbling, 36
typy, 37
wasne, 41
waciwoci, 38
zdarzenie
beforecopy, 103
beforecut, 103
beforepaste, 104
blur, 36
change, 36, 87
change.tabs, 42
click, 36
copy, 103
cut, 103
dblclick, 36
document.ready, 225, 227
DOMContentLoaded, 39
drag, 100
dragend, 100
dragenter, 100
dragleave, 100
dragover, 100, 102
dragstart, 100
drop, 100, 101
focus, 36
hashchange, 77
Kup książkę
Poleć książkę
Skorowidz
_ 263
load, 110
mousemove, 36
mouseout, 36
mouseover, 36
onerror, 105
onhashchange, 187
onload, 105
onmessage, 115
onopen, 115
onprogress, 105
paste, 104
popevent, 80
popstate, 80
progress, 110
submit, 36
zmienna self, 225
zmienne globalne, 31
eksport, 66
import, 66
znaczniki ETags, 152
znak
dolara, 221
dwukropka, 101
hash, 221
podkrelenia, 31
ukonika, 150
wykrzyknika, 78
Zombie.js, 134
dania Ajax, 56, 226
dania HTTP, 55, 63
danie
DELETE, 56
GET, 56, 57
OPTIONS, 58
POST, 56, 63
PUT, 63
Kup książkę
Poleć książkę
Kup książkę
Poleć książkę