Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00270 006384 12422163 na godz. na dobę w sumie
JavaScript. Aplikacje WWW - książka
JavaScript. Aplikacje WWW - książka
Autor: Liczba stron: 264
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-3887-1 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> webmasterstwo >> javascript - programowanie
Porównaj ceny (książka, ebook, audiobook).

Poznaj potencjał języka JavaScript!

Język JavaScript od zawsze jest obecny w przeglądarkach internetowych. W swojej historii miewał okresy lepsze i gorsze - czasem bywał wręcz znienawidzony przez użytkowników. Te czasy jednak minęły! Obecnie jego możliwości są wręcz oszałamiające. Ciężko wyobrazić sobie współczesną popularną aplikację internetową, która nie korzystałaby z jego dobrodziejstw. W najnowszej odsłonie HTML5 jego potencjał jest jeszcze większy!

Sprawdź sam, jak wykorzystać JavaScript do stworzenia aplikacji, która zaskoczy użytkowników. Budowanie w tym języku dużych internetowych aplikacji, które zaoferują użytkownikom funkcje obecne dotąd wyłącznie w aplikacjach biurkowych, wymaga utrzymywania stanu aplikacji po stronie klienta - a to nie jest łatwe zadanie. Dzięki tej książce poznasz szczegółowy opis czynności, jakie trzeba wykonać, aby zaimplementować nowoczesną aplikację, a potem opanujesz skuteczne metody korzystania z mechanizmu WebSockets, operowania na plikach oraz modelowania danych. Ponadto zgłębisz niuanse nowego API oraz dowiesz się, jakie są najlepsze techniki debugowania i analizowania wydajności Twojej aplikacji. Ta książka to długo oczekiwana pozycja, w całości poświęcona zaawansowanemu wykorzystaniu języka JavaScript!

Z tą książką błyskawicznie opanujesz:

Twórz nowoczesne aplikacje przy użyciu najlepszych dostępnych narzędzi!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

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. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis treļci Przedmowa ...............................................................................................................................9 Poczñtki Nadawanie struktury Czym jest MVC? Model Widok Kontroler 1. MVC i klasy ....................................................................................................................17 17 18 19 19 20 21 22 23 24 25 26 27 29 31 32 Ku modularyzacji, tworzenie klas Dodawanie funkcji do klas Dodawanie metod do wäasnej biblioteki klas Dziedziczenie klas przy uĔyciu prototypu Dodawanie dziedziczenia do biblioteki klas Wywoäywanie funkcji Kontrola zasiögu we wäasnej bibliotece klas Dodawanie funkcji prywatnych Biblioteki klas 2. Zdarzenia i ich nasĥuchiwanie ....................................................................................35 35 36 37 37 39 40 40 41 41 43 Nasäuchiwanie zdarzeþ KolejnoĈè zdarzeþ Anulowanie zdarzeþ Obiekt zdarzenia Event Biblioteki zdarzeþ Zmiana kontekstu Delegowanie zdarzeþ Wäasne zdarzenia Wäasne zdarzenia i moduäy rozszerzajñce jQuery Zdarzenia inne niĔ zdarzenia DOM 3 MVC i przestrzenie nazw Tworzenie ORM Dziedziczenie przez prototypy Dodawanie wäaĈciwoĈci ORM Utrzymywanie rekordów Dodawanie obsäugi identyfikatorów Adresowanie odwoäaþ ãadowanie danych 3. Modele i dane ..............................................................................................................47 47 48 49 50 51 52 53 54 55 55 59 59 60 60 61 63 Wypeänienie ORM danymi Przechowywanie danych lokalnie Dodanie mechanizmu przechowywania danych lokalnie do ORM Przesyäanie nowych rekordów na serwer Wplatanie danych ãadowanie danych przy uĔyciu Ajax JSONP Bezpieczeþstwo Ĕñdaþ miödzy domenami Wzorzec moduäu Dodawanie kontekstu Import zmiennych globalnych Eksport zmiennych globalnych 4. Kontrolery i stany ........................................................................................................65 66 66 66 67 68 69 70 72 74 76 76 77 77 78 Wydzielanie kodu do oddzielnej biblioteki ãadowanie kontrolerów po zaäadowaniu dokumentu Dostöp do widoków Delegowanie zdarzeþ Korzystanie z hash value adresu URL Wykrywanie zmian hash value Ajax Crawling Wykorzystanie API History HTML5 Maszyny stanów Routing Dynamiczne generowanie widoków Szablony 5. Widoki i szablony ........................................................................................................ 81 81 82 84 85 86 87 Pomocnicze funkcje obsäugi szablonów Przechowywanie szablonów Wiñzanie modeli Wiñzanie 4 _ Spis treļci CommonJS Biblioteki äadowania moduäów Deklarowanie moduäu Moduäy i przeglñdarka 6. Zarzédzanie zaleŜnoļciami .........................................................................................89 90 90 91 92 92 93 94 95 96 96 Opakowywanie moduäów Rozwiñzania alternatywne wzglödem moduäów Yabble RequireJS LABjs FUBC Obsäuga w przeglñdarkach Pobieranie informacji na temat plików Kontrolka do przesyäania plików na serwer Przeciñganie i upuszczanie Przeciñganie Upuszczanie Anulowanie domyĈlnej obsäugi przeciñgania i upuszczania 7. Praca z plikami .............................................................................................................97 97 98 98 99 100 101 102 103 103 104 105 106 107 107 109 Wäasne przyciski przeglñdarki ãadowanie plików na serwer ćledzenie postöpu operacji DuĔe obiekty binarne oraz fragmenty pliku Kopiowanie Wklejanie Kopiowanie i wklejanie Czytanie plików Przesyäanie pliku na serwer przy uĔyciu przeciñgania i upuszczania oraz biblioteki jQuery Obszar upuszczania Przesyäanie pliku na serwer 111 111 111 Historia dziaäania w czasie rzeczywistym WebSockets 8. Praca w sieci w czasie rzeczywistym .........................................................................113 113 114 118 119 121 Architektura czasu rzeczywistego Odczuwana prödkoĈè dziaäania Node.js i Socket.IO Spis treļci _ 5 Testy jednostkowe Asercje QUnit Jasmine Sterowniki Testowanie niezaleĔne 9. Testowanie i usuwanie bĥýdów ................................................................................ 123 125 125 126 129 131 134 134 136 137 137 138 138 140 141 142 143 144 145 UĔywanie debuggera Analiza Ĕñdaþ sieciowych Profilowanie i analiza czasu Testowanie rozproszone ćwiadczenie wsparcia Inspektory Web Inspector Firebug Zombie Ichabod Konsola Funkcje pomocnicze konsoli 10. WdraŜanie .................................................................................................................. 149 149 150 152 153 154 155 156 WydajnoĈè Wykorzystanie pamiöci podröcznej Minifikacja Kompresja Gzip Korzystanie z CDN Audytory Zasoby Instalacja Klasy Tworzenie instancji Rozszerzanie klas Kontekst 11. Biblioteka Spine ..........................................................................................................157 157 158 158 159 160 161 161 163 163 164 164 Pobieranie rekordów Zdarzenia modelu Weryfikacja poprawnoĈci Zapisywanie Zdarzenia Modele 6 _ Spis treļci Kontrolery Wskazywanie kontekstu WäaĈciwoĈè elements Delegowanie zdarzeþ Zdarzenia kontrolera Zdarzenia globalne Wzorzec Render Wzorzec Element Aplikacja do zarzñdzania danymi kontaktowymi Model Contact Kontroler Sidebar Kontroler Contacts Kontroler App 166 167 167 168 168 169 170 170 171 173 173 175 178 Modele i atrybuty Modele Kolekcje Widoki Kontrola kolejnoĈci elementów w kolekcji 12. Biblioteka Backbone .................................................................................................. 179 180 180 181 183 183 184 184 185 186 188 189 189 190 192 Wypeänianie kolekcji Po stronie serwera Implementacja wäasnej logiki Generowanie widoków Delegowanie zdarzeþ Wiñzanie i kontekst Kontrolery Synchronizacja z serwerem Aplikacja do zarzñdzania listñ rzeczy do zrobienia Konfiguracja Klasy 13. Biblioteka JavaScriptMVC ......................................................................................... 199 200 200 200 201 201 201 202 202 Tworzenie instancji Wywoäywanie metody bazowej OkreĈlanie kontekstu Dziedziczenie statyczne Introspekcja Przykäadowy model Spis treļci _ 7 Model Atrybuty i dane obserwowalne Rozszerzanie modeli Metody ustawiajñce wartoĈci WartoĈci domyĈlne Metody pomocnicze Enkapsulacja usäug Przeksztaäcanie typów Zdarzenia CRUD Wykorzystanie w widokach szablonów dziaäajñcych po stronie klienta Sposób uĔycia Modyfikatory jQuery ãadowanie widoku ze znacznika skryptu $.View i subszablony Obiekty wstrzymane Pakowanie, äadowanie wstöpne i wydajnoĈè $.Controller: fabryka moduäów rozszerzajñcych jQuery Informacje ogólne Tworzenie instancji kontrolera Wiñzanie zdarzeþ Akcje szablonowe Kompletne rozwiñzanie: abstrakcyjna lista czynnoĈci CRUD 203 203 205 205 206 206 207 209 210 210 211 211 212 212 212 213 213 215 216 216 217 218 A. Wprowadzenie do biblioteki jQuery ........................................................................ 221 B. Rozszerzenia CSS ....................................................................................................... 231 C. Przegléd CSS3 ............................................................................................................235 Skorowidz .............................................................................................................................255 8 _ Spis treļci ROZDZIAĤ 3. Modele i dane Gdy aplikacja ma utrzymywaè stan na kliencie, jednym z wyzwaþ stojñcym przed programi- stñ jest zapewnienie odpowiedniego zarzñdzania danymi. Standardowo w momencie wy- woäania strony dane pobiera siö bezpoĈrednio z bazy danych, a wynik ich przetwarzania umieszcza siö bezpoĈrednio na stronie. Jednak w stanowych aplikacjach JavaScript proces za- rzñdzania danymi przebiega zupeänie inaczej. Nie obowiñzuje w nich model wywoäanie- odpowiedĒ, nie sñ takĔe dostöpne zmienne na serwerze. Dane sñ za to pobierane zdalnie i tym- czasowo przechowywane po stronie klienta. Wprawdzie zaimplementowanie odpowiedniego mechanizmu moĔe byè doĈè trudnym za- daniem, jednak uzyska siö dziöki temu co najmniej kilka korzyĈci. Na przykäad dostöp do da- nych znajdujñcych siö po stronie klienta jest praktycznie natychmiastowy, tak jakby dane po- bierane byäy z pamiöci. MoĔe to zdecydowanie poprawiè dziaäanie interfejsu aplikacji, poniewaĔ kaĔda czynnoĈè uĔytkownika skutkuje natychmiastowym zwróceniem wyniku. Dziöki temu aplikacja znajduje zdecydowanie wiöksze uznanie u uĔytkowników. Aby odpowiednio skonstruowaè mechanizm przechowywania danych po stronie klienta, trzeba najpierw szczegóäowo przeanalizowaè wszystkie okolicznoĈci. Zadanie najeĔone jest róĔnorodnymi przeszkodami i puäapkami, w które wpadajñ zwäaszcza poczñtkujñcy progra- miĈci — 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ñ takĔe najbardziej zalecane wzorce i praktyki. MVC i przestrzenie nazw Aby opracowaè takñ architekturö aplikacji, która bödzie przejrzysta i äatwa w utrzymaniu, trzeba przede wszystkim zapewniè peänñ separacjö widoków aplikacji, jej stanu i danych. W przypadku wykorzystania wzorca MVC zarzñdzanie danymi odbywa siö w modelu („M” w nazwie MVC). Modele powinny byè rozäñczne wzglödem widoków i kontrolerów. Natomiast logika wyznaczajñca 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 moĔna zapewniè przez uczynienie ich wäaĈciwoĈciami obiektu. Na przykäad: var User = { records: [ /* ... */ ] }; 47 Tablica uĔytkowników ma teraz odpowiedniñ przestrzeþ nazw User.records. Funkcje zwiñza- ne z obsäugñ uĔytkowników równieĔ mogñ naleĔeè do przestrzeni nazw wyznaczanej przez model User. MoĔna na przykäad zaimplementowaè funkcjö fetchRemote(), która bödzie pobieraè z serwera dane uĔytkownika: var User = { records: [], fetchRemote: function(){ /* ... */ } }; Umieszczenie wszystkich wäaĈciwoĈci modelu w przestrzeni nazw zapewni, Ĕe nie wystñpiñ Ĕadne konflikty, a jednoczeĈnie utrzymana zostanie zgodnoĈè z paradygmatem MVC. Poza tym zmniejszy siö zagroĔenie, Ĕe tworzony kod Ēródäowy zamieni siö z biegiem czasu w nie- zrozumiaäñ spiralö funkcji i wywoäaþ zwrotnych. Zakres wykorzystania przestrzeni nazw moĔna jeszcze pogäöbiè i umieĈciè wszystkie funkcje operujñce na instancjach uĔytkowników w rzeczywistych obiektach uĔytkowników. Przyjmij- my, Ĕe na rekordzie uĔytkownika zaimplementowana jest funkcja destroy(). Odnosi siö ona do konkretnego uĔytkownika, zatem powinna byè wywoäywana na instancji obiektu User: var user = new User; user.destroy() Aby osiñgnñè zamierzony efekt, naleĔy uczyniè z User klasö, a nie zwykäy obiekt: var User = function(atts){ this.attributes = atts || {}; }; User.prototype.destroy = function(){ /* ... */ }; Natomiast wszelkie funkcje i wäaĈciwoĈci, które nie dotyczñ konkretnego uĔytkownika, mogñ byè wäaĈciwoĈciami bezpoĈrednio obiektu User: User.fetchRemote = function(){ /* ... */ }; Wiöcej ciekawych informacji na temat przestrzeni nazw moĔna znaleĒè na blogu Petera Michaux, który opublikowaä bardzo ciekawy artykuä na ten wäaĈnie 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 zarzñdzania danymi, a takĔe znacznie uäatwiajñ uĔycie modeli w aplikacji JavaScript. Za pomocñ ORM moĔna na przykäad powiñzaè model ze zdalnym serwerem — w wyniku takiego powiñzania wszelkie zmiany w instancjach modelu bödñ wysyäane w tle do serwera w ramach wywoäaþ Ajax. MoĔna takĔe powiñzaè instancjö modelu z elementem HTML, dziöki czemu wszelkie zmiany w instancji modelu spowodujñ odpowiedniñ zmianö w widoku. Przykäady te zostanñ rozwiniöte nieco póĒniej, a na razie zobaczmy, jak tworzy siö ORM. 48 _ Rozdziaĥ 3. Modele i dane Zasadniczo ORM jest po prostu warstwñ obiektów opakowujñcñ jakieĈ dane. Standardowo ORM stanowiñ warstwö abstrakcji dla baz danych SQL, jednak w naszym przypadku ORM bödzie po prostu warstwñ abstrakcji dla typów danych JavaScriptu. Zaletñ takiej dodatkowej warstwy jest to, Ĕe podstawowy zbiór danych moĔna rozszerzyè o dodatkowe rozwiñzania przez dodanie wäasnych funkcji i wäaĈciwoĈci. Dziöki temu moĔna dodawaè mechanizmy wery- fikacji poprawnoĈci albo utrzymywania danych, obserwatory czy wywoäania zwrotne do ser- wera, a jednoczeĈnie nadal mieè moĔliwoĈè wielokrotnego wykorzystywania kodu Ēródäowego. Dziedziczenie przez prototypy Do stworzenia naszej wäasnej biblioteki ORM wykorzystamy Object.create(), co jest podej- Ĉciem nieco odmiennym od przykäadów opisywanych w rozdziale 1, w których korzystali- Ĉmy z klas. Nowe podejĈcie pozwoli nam jednak na skorzystanie z dziedziczenia przez pro- totypy zamiast uĔywania funkcji konstruktorów i säowa kluczowego new. Funkcja Object.create() przyjmuje jeden argument — obiekt prototypu — i zwraca nowy obiekt z przekazanym obiektem prototypu. Inaczej mówiñc, przekazuje siö do niej obiekt, a funkcja zwraca nowy obiekt, potomny po obiekcie przekazanym. Funkcja Object.create() zostaäa dopiero niedawno dodana do specyfikacji ECMAScript, 5th Edition i dlatego jeszcze nie wszystkie przeglñdarki jñ obsäugujñ — naleĔy do nich miödzy innymi IE. Nie jest to jednak wielki problem, poniewaĔ w razie potrzeby obsäugö tej funkcji moĔna zaimplementowaè samemu: if (typeof Object.create !== function ) Object.create = function(o) { function F() {} F.prototype = o; return new F(); }; PowyĔszy przykäad pochodzi z artykuäu Douglasa Crockforda na temat dziedziczenia przez prototypy (http://javascript.crockford.com/prototypal.html). Warto siö z nim zapoznaè, aby lepiej poznaè mechanizmy rzñdzñce prototypami i dziedziczeniem w jözyku JavaScript. Utworzymy teraz obiekt Model, którego zadaniem bödzie 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); Tworzenie ORM _ 49 instance.parent = this; instance.init.apply(instance, arguments); return instance; } }; Programistów, którzy nie poznali dotychczas funkcji Object.create(), definicja Model moĔe nieco zniechöcaè, wiöc rozäoĔymy jñ na czynniki pierwsze. Funkcja create() zwraca nowy obiekt, który dziedziczy po obiekcie Model. W ten sposób tworzone bödñ 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 wĥaļciwoļci ORM JeĈli teraz do Model dodamy wäaĈciwoĈci, stanñ siö one dostöpne we wszystkich modelach potomnych: // Dodanie wáaĞciwoĞci obiektu jQuery.extend(Model, { find: function(){} }); // Dodanie wáaĞciwoĞci 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 pötli for i wykonaniu w niej röcznego kopio- wania wäaĈciwoĈci. Tak wäaĈnie postöpujemy w funkcji load(). Teraz wäaĈciwoĈci obiektu i instancji sñ propagowane w dóä, do konkretnych modeli: assertEqual( typeof Asset.find, function ); W praktyce liczba dodawanych wäaĈciwoĈci bödzie doĈè znaczna, dlatego najlepiej jest od razu zawrzeè w obiekcie Model funkcje extend() i include(): var Model = { /* ... ciĊcie ... */ 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); 50 _ Rozdziaĥ 3. Modele i dane } }; // Dodanie wáaĞciwoĞci obiektu Model.extend({ find: function(){} }); // Dodanie wáaĞciwoĞci instancji Model.include({ init: function(atts) { /* ... */ }, load: function(attributes){ /* ... */ } }); MoĔna 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 zapamiötywania od- woäaþ 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 bödzie dodawany do modelu w momencie zapisywania instancji modelu i usuwany z obiektu modelu, gdy usu- wana bödzie 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 moĔna zmieniaè istniejñcñ instancjö? To proste — wystarczy zmieniè odwo- äanie do obiektu: Model.include({ update: function(){ this.parent.records[this.id] = this; } }); Warto takĔe zaimplementowaè wygodnñ funkcjö odpowiedzialnñ za zapisywanie instancji, tak by nie trzeba byäo póĒniej sprawdzaè, czy instancja zostaäa zapisana juĔ wczeĈniej albo czy trzeba tö instancjö utworzyè: // Zapisanie obiektu do records i zapamiĊtanie odwoáania do obiektu Model.include({ save: function(){ this.newRecord ? this.create() : this.update(); } }); Tworzenie ORM _ 51 Wreszcie dobrze teĔ zaimplementowaè funkcjö find(), która bödzie wyszukiwaè zasoby o wska- zanym identyfikatorze: Model.extend({ // Znalezienie zasobu o danym ID lub rzucenie wyjątku find: function(id){ return this.records[id] || throw( Rekord nieznany ); } }); ORM w najprostszej postaci jest juĔ gotowy, moĔna 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 obsĥugi identyfikatorów Obecnie za kaĔdym razem, gdy zapisywany jest rekord, trzeba röcznie zdefiniowaè jego identyfikator ID. To przykry obowiñzek, ale na szczöĈcie moĔna to zadanie zautomatyzowaè. Najpierw potrzebny jest jakiĈ mechanizm generowania identyfikatorów — moĔe nim byè ge- nerator identyfikatorów GUID (ang. Globally Unique Identifier). Z technicznego punktu wi- dzenia JavaScript nie moĔe generowaè peänoprawnych, 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 wröcz uĔywa siö lamp z zawartoĈciñ cieczy oraz wosku, które po rozgrzaniu tworzñ róĔne efekty kolorystyczne! Jednak natywna funkcja Math.random(), choè pseudolosowa, w zu- peänoĈci nam wystarczy. Robert Kieffer napisaä prosty i zwiözäy 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 moĔemy jego kod Ēródäowy zaprezentowaè w caäoĈci: 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 wiöc funkcjö, która generuje identyfikatory GUID, zatem zintegrowanie jej z ORM nie naströczy juĔ trudnoĈci. Wystarczy w tym celu zmieniè kod funkcji create(): 52 _ Rozdziaĥ 3. Modele i dane Model.extend({ create: function(){ if ( !this.id ) this.id = Math.guid(); this.newRecord = false; this.parent.records[this.id] = this; } }); Od teraz kaĔdy nowo utworzony rekord bödzie miaä identyfikator w postaci losowego GUID: ar asset = Asset.init(); asset.save(); asset.id //= 54E52592-313E-4F8B-869B-58D61F00DC74 Adresowanie odwoĥaħ UwaĔni Czytelnicy zapewne zwrócili uwagö na bäñd zwiñzany z odwoäaniami w naszej bi- bliotece ORM. Nie klonujemy instancji ani wtedy, gdy zostajñ zwrócone przez find(), ani w momencie ich zapisywania, przez co jeĈli zmienimy którñĈ z ich wäaĈciwoĈci, zmiana dotknie oryginalnego zasobu. Jest to powaĔny problem, poniewaĔ oczekujemy, Ĕe zasoby bödñ siö zmieniaè jedynie po wykonaniu funkcji update(): var asset = new Asset({name: foo }); asset.save(); // Asercja przekazuje prawidáowo assertEqual( Asset.find(asset.id).name, foo ); // Zmiana wáaĞciwoĞci bez wywoáywanai update() asset.name = wem ; // O nie! Asercja koĔczy siĊ niepowodzeniem, poniewaĪ nazwą jest teraz wem assertEqual( Asset.find(asset.id).name, foo ); Aby wyeliminowaè bäñd, w trakcie dziaäania find() utworzymy nowy obiekt. Ponadto konieczne bödzie 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); } }); Adresowanie odwoĥaħ _ 53 Jest jeszcze jeden problem — Model.records to obiekt, który jest wspóäuĔytkowany przez wszystkie modele: assertEqual( Asset.records, Person.records ); Daje to niepoĔñdany efekt wymieszania ze sobñ wszystkich rekordów: var asset = Asset.init(); asset.save(); assert( asset in Person.records ); Rozwiñzanie polega na tym, by za kaĔdym razem, gdy tworzony jest nowy model, ustawiaè teĔ nowy obiekt records. Model.created() jest wywoäaniem zwrotnym do tworzenia nowego obiektu, dlatego moĔna w nim ustawiaè dowolne obiekty dotyczñce tego wäaĈnie modelu: Model.extend({ created: function(){ this.records = {}; } }); Ĥadowanie danych JeĈli aplikacja internetowa dziaäa w jakiejĈ czöĈci poza przeglñdarkñ, konieczne jest umoĔli- wienie äadowania danych zdalnie z serwera. Zazwyczaj w trakcie uruchamiania aplikacji äa- dowany jest jakiĈ podzbiór danych, a po wykonaniu okreĈlonych czynnoĈci przez uĔytkow- nika aplikacja äaduje kolejne potrzebne dane. ZaleĔnie od rodzaju aplikacji i iloĈci danych komplet danych moĔna pozyskiwaè od razu w momencie pierwszego äadowania strony. Jest to przypadek idealny, poniewaĔ wówczas uĔytkownicy nie bödñ juĔ musieli czekaè na zaäa- dowanie dodatkowych danych. Jednak w przypadku wiökszoĈci aplikacji rozwiñzanie takie nie wchodzi w grö, poniewaĔ zbiór potrzebnych danych jest zbyt duĔy, by bez problemu zmieĈciä siö w pamiöci dostöpnej dla przeglñdarki. Tylko dziöki zaäadowaniu danych od razu przy starcie aplikacji bödzie moĔna zapewniè uĔytkownikom komfort pracy z niñ, a czas odpowiedzi zredukowaè do minimum. Istnieje jednak istotna róĔnica miödzy poczñtkowym äadowaniem danych, które rzeczywiĈcie sñ po- tem wykorzystywane, a äadowaniem danych nadmiarowych, które nigdy nie zostanñ uĔyte. Trzeba zatem przewidzieè, których danych uĔytkownicy bödñ potrzebowaè, albo dokonaè odpowiednich pomiarów juĔ w trakcie pracy aplikacji. Na przykäad jeĈli äadowana jest lista stronicowana, to dlaczego nie zaäadowaè od razu za- wartoĈci nastöpnej strony, aby przeäñczanie miödzy stronami nastöpowaäo od razu? Albo, co daäoby jeszcze lepszy efekt, po prostu wyĈwietliè däugñ listö i automatycznie äadowaè i wstawiaè do niej dane, gdy uĔytkownik bödzie tö listö przewijaä (säuĔy do tego wzorzec nie- skoþczonego suwaka). Im mniejsze bödzie opóĒnienie widoczne dla uĔytkownika, tym lepiej. NaleĔy zapewniè, Ĕe w trakcie pobierania nowych danych interfejs uĔytkownika nie bödzie siö blokowaä. Warto wyĈwietliè jakiĈ wskaĒnik postöpu äadowania danych, ale caäoĈè interfej- su powinna przez caäy czas byè dostöpna dla uĔytkownika. Liczba sytuacji, w której bödzie dochodziäo do zablokowania interfejsu, powinna byè jak najmniejsza, a najlepiej, by w ogóle do tego nie dochodziäo. 54 _ Rozdziaĥ 3. Modele i dane Dane moĔna wplataè w definicjö strony bñdĒ pobieraè je w oddzielnych Ĕñdaniach HTTP za pomocñ Ajax lub JSONP. Polecam raczej to drugie rozwiñzanie, poniewaĔ wplatanie w kod strony duĔych iloĈci danych powoduje znaczne zwiökszenie rozmiaru strony, natomiast dziöki pobieraniu danych równolegle z äadowaniem strony skraca siö caäkowity czas jej äa- dowania. Technologie AJAX i JSONP pozwalajñ dodatkowo umieszczaè strony HTML w pa- miöci podröcznej, dziöki czemu nie trzeba ich äadowaè na nowo przy kaĔdym kolejnym wywoäaniu. Wplatanie danych Nie polecam stosowania tego podejĈcia z powodów opisanych w poprzednim akapicie, jed- nak technika wplatania danych moĔe byè w niektórych okolicznoĈciach przydatna, zwäaszcza 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 bezpoĈrednio w kodzie strony. W technologii Ruby on Rails odpowiednie rozwiñzanie miaäoby 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 uĔytkownika. Metoda raw zapobiega wstawianiu znaków ucieczki przez JSON. W wyniku przetworzenia strony jej kod HTML bödzie wyglñdaä tak: script type= text/javascript var User = {}; User.records = [{ first_name : Alex }]; /script JavaScript moĔe przetwarzaè dane JSON bez ich dodatkowego przeksztaäcania, poniewaĔ JSON ma takñ samñ strukturö jak obiekty jözyka JavaScript. Ĥadowanie danych przy uŜyciu Ajax ãadowanie danych przy uĔyciu Ajax to chyba pierwsza metoda äadowania zdalnych danych, która przychodzi na myĈl programistom, gdy mowa o wywoäaniach w tle. To nie przypadek: technologia ta zostaäa wypróbowana, przetestowana i udostöpniona we wszystkich wspóä- czesnych przeglñdarkach. Ajax nie jest oczywiĈcie pozbawiony wad — historia rozwoju tej technologii, dla której nie istniaäy Ĕadne standardy, zakoþczyäa siö powstaniem niespójnych API. Przez to wäaĈnie, oraz ze wzglödu na wymogi bezpieczeþstwa przeglñdarek 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 duĔym prawdopodobieþstwem moĔna zaäoĔyè, Ĕe i tak wiökszoĈè programistów ostatecznie wykorzysta bibliotekö, na przykäad jQuery, która bödzie udostöpniaè warstwö abstrakcji nad API Ajax i ukrywaè przed programistñ róĔnice w obsäudze technologii miödzy poszczególnymi przeglñdarkami. Dlatego w tym punkcie bödzie mowa o API biblioteki jQuery, a nie o samej klasie XMLHttpRequest. Ĥadowanie danych _ 55 API Ajax biblioteki jQuery zawiera jednñ funkcjö niskiego poziomu o nazwie jQuery.ajax() oraz kilka jej abstrakcji wyĔszego poziomu, dziöki którym znacznie zmniejsza siö iloĈè wy- maganego do napisania kodu Ēródäowego. Funkcja jQuery.ajax() przyjmuje miödzy innymi zbiór ustawieþ parametrów wywoäania, typ zawartoĈci oraz odwoäania zwrotne. W momencie wywoäania funkcji Ĕñdanie jest asynchronicznie wykonywane w tle. url Adres URL Ĕñdania. DomyĈlnym adresem URL jest adres bieĔñcej strony. success Funkcja, która ma zostaè wywoäana, gdy Ĕñdanie zakoþczy siö powodzeniem. Wszystkie dane zwrócone przez serwer sñ przekazywane do funkcji jako jej parametr. contentType Ustawia nagäówek Content-Type Ĕñdania. JeĔeli Ĕñdanie zawiera dane, domyĈlnym typem zawartoĈci jest application/x-www-form-urlencoded, które sprawdza siö w wiökszoĈci przy- padków. data Dane, które naleĔy przesäaè do serwera. JeĔeli nie jest to ciñg znaków, jQuery je zseriali- zuje i zakoduje. type Metoda HTTP, której naleĔy uĔyè do wykonania Ĕñdania: GET, POST lub DELETE. Metodñ domyĈlnñ 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. JeĔeli dataType nie zostanie okreĈlony, jQuery spróbuje ten typ odgadnñè na podstawie typu MIME odpowiedzi z serwera. Obsäugiwane sñ nastöpujñce wartoĈci 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 uĔyciu dokäadnego parsera. jsonp Oznacza format JSONP, który zostanie przedstawiony w dalszej czöĈci ksiñĔki. Jako przykäad zdefiniujemy proste Ĕñdanie Ajax, które wyĈwietli dane zwrócone przez serwer: jQuery.ajax({ url: /ajax/endpoint , type: GET , success: function(data) { alert(data); } }); 56 _ Rozdziaĥ 3. Modele i dane Jednak definiowanie wszystkich opcji jest doĈè uciñĔliwe. Na szczöĈcie jQuery udostöpnia kilka krótszych rozwiñzaþ. Funkcja jQuery.get() pobiera adres URL, opcjonalne dane oraz wywoäanie zwrotne: jQuery.get( /ajax/endpoint , function(data){ $( .ajaxResult ).text(data); }); Natomiast aby wysäaè kilka parametrów w ramach Ĕñdania GET, moĔna to zrobiè nastöpujñco: jQuery.get( /ajax/endpoint , {foo: bar }, function(data){ /* ... */ }); JeĔeli spodziewamy siö, Ĕe serwer zwróci dane JSON, trzeba uĔyè funkcji jQuery.getJSON(), która automatycznie ustawia opcjö dataType Ĕñdania na json : jQuery.getJSON( /json/endpoint , function(json){ /* ... */ }); Dostöpna jest analogiczna funkcja jQuery.post(), która równieĔ przyjmuje adres URL, dane i wywoäanie zwrotne: jQuery.post( /users , {first_name: Alex }, function(result){ /* ĩądanie POST Ajax zakoĔczyáo siĊ powodzeniem */ }); Aby skorzystaè z innych metod HTTP, czyli DELETE, HEAD i OPTIONS, trzeba uĔyè niskopoziomowej funkcji jQuery.ajax(). W tym punkcie przedstawiono krótki opis API Ajax biblioteki jQuery. Wiöcej informacji na ten temat moĔna znaleĒè w kompletnej dokumentacji dostöpnej na stronie pod adresem http://api.jquery.com/category/ajax. Istotnym ograniczeniem Ajax jest obowiñzujñca w tej technologii zasada toĔsamego pocho- dzenia (ang. same origin policy), która ogranicza moĔliwoĈè obsäugi 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 wysyäane jest Ĕñdanie Ajax, wraz z nim wysyäane sñ wszystkie dane cookie domeny. Dla serwera zdalnego jest to znak, Ĕe Ĕñdanie pochodzi od zalogowanego uĔytkownika. Gdyby nie obowiñzywaäa zasada toĔsamego pochodzenia, po- tencjalny napastnik mógäby pobraè wszystkie wiadomoĈci pocztowe innej osoby z jej skrzynki Gmail, zmieniaè statusy na czyimĈ profilu Facebooka albo publikowaè wiadomoĈci w czyimĈ imieniu na Twitterze — jednym säowem, byäoby to istotne zagroĔenie bezpieczeþstwa. Jednak zasada toĔsamego pochodzenia, która jest istotnym elementem systemu bezpieczeþ- stwa w sieci WWW, nakäada na programistów bardzo niewygodne ograniczenia, poniewaĔ odbiera im moĔliwoĈè korzystania z w peäni bezpiecznych zasobów zdalnych. Inne technologie, na przykäad Adobe Flash i Java, udostöpniajñ obejĈcia tego problemu w postaci plików z re- guäami dostöpu do innych domen. Do tego towarzystwa doäñczyä ostatnio Ajax wraz ze swoim standardem o nazwie CORS (http://www.w3.org/TR/access-control), wyznaczajñcym zasady wspóä- uĔytkowania zasobów miödzy domenami. Dziöki CORS moĔna wyäamaè siö z zasady toĔsamego pochodzenia i uzyskaè dostöp do au- toryzowanych, zdalnych serwerów. Specyfikacja standardu CORS zostaäa zaimplementowana w najwaĔniejszych przeglñdarkach, dlatego jeĈli tylko nie jest uĔywana przeglñdarka IE6, nie powinno byè z tym standardem wiökszych problemów. Ĥadowanie danych _ 57 Zakres obsäugi standardu CORS w poszczególnych przeglñdarkach opisano poniĔej: x IE = 8 (z pewnymi ograniczeniami). x Firefox = 3. x Safari: peäna obsäuga. x Chrome: peäna obsäuga. x Opera: brak obsäugi. Korzystanie z CORS nie sprawia Ĕadnych problemów. Aby autoryzowaè dostöp do wäasnego serwera, wystarczy do nagäówka zwracanych odpowiedzi dodawaè te dwa wiersze: Access-Control-Allow-Origin: przyklad.com Access-Control-Request-Method: GET,POST PowyĔszy nagäówek autoryzuje Ĕñdania GET i POST do innej domeny wykonywane z domeny przyklad.com. Gdy wartoĈci jest wiöcej niĔ jedna, naleĔy oddzieliè je od siebie przecinkami, tak samo jak w przypadku metod GET, POST powyĔej. Aby umoĔliwiè dostöp z wiöcej niĔ jednej domeny, wystarczy zawrzeè ich listö oddzielonñ od siebie przecinkami w nagäówku Access-Control-Allow-Origin. Natomiast aby zezwoliè na dostöp z dowolnej domeny, naleĔy w nagäówku Origin wpisaè znak gwiazdki (*). Niektóre przeglñdarki, na przykäad Safari, najpierw wykonujñ Ĕñdanie OPTIONS, aby spraw- dziè, czy kolejne Ĕñdanie bödzie dozwolone. Z kolei Firefox przeĈle od razu wäaĈciwe Ĕñdanie i dopiero w przypadku braku nagäówków CORS rzuci wyjñtek. W trakcie implementowania kodu Ēródäowego trzeba wziñè pod uwagö te róĔnice w dziaäaniu serwerów. Standard CORS pozwala nawet na autoryzowanie Ĕñdaþ z niestandardowymi nagäówkami. SäuĔy do tego nagäówek Access-Control-Request-Headers: Access-Control-Request-Headers: Authorization Tak skonstruowany nagäówek oznacza, Ĕe klienty mogñ dodawaè wäasne nagäówki do Ĕñdaþ Ajax i na przykäad 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 obsäugiwany 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ä wäasny obiekt XDomainRequest (http://msdn. microsoft.com/en-us/library/cc288060 28VS.85 29.aspx), którym w przypadku Ĕñdaþ miödzy domenami naleĔy zastñpiè 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 przykäad obiekt obsäuguje tylko metody GET i POST, nie sñ obsäugiwane nagäówki uwierzytelniania ani nagäówki niestandardowe, a w koþcu — i to jest najdziwniejsze — spoĈród typów zawartoĈci obsäugiwany jest wyäñcznie Content-Type: text/plain. Zatem aby skorzystaè z CORS w IE, trzeba — oprócz uĔycia prawidäowych na- gäówków Access-Control — opracowaè odpowiednie obejĈcia dla wspomnianych przed chwilñ ograniczeþ. 58 _ Rozdziaĥ 3. Modele i dane JSONP JSONP (http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp), albo inaczej JSON z wy- peänianiem, to technologia opracowana przed zdefiniowaniem standardu CORS. JSONP sta- nowi kolejne narzödzie do pobierania danych ze zdalnych serwerów. Mechanizm dziaäania JSONP polega na tym, Ĕe definiowany jest znacznik skryptu, który wskazuje na koþcówkö JSONP. Tam wäaĈnie zwracane dane sñ opakowywane w wywoäanie funkcji. Znaczniki skryp- tów nie podlegajñ ograniczeniom zwiñzanym z komunikacjñ miödzy domenami, a poza tym opisywana technika jest obsäugiwana wäaĈciwie przez kaĔdñ przeglñdarkö. PoniĔej przedstawiono znacznik skryptu, który wskazuje na zdalny serwer: script src= http://przyklad.com/dane.json /script Koþcówka dane.json zwraca obiekt JSON opakowany w wywoäanie funkcji: jsonCallback({ data : foo }) Nastöpnie definiuje siö funkcjö dostöpnñ globalnie. Gdy tylko skrypt zostanie zaäadowany, nastñpi wywoäanie tej funkcji: window.jsonCallback = function(result){ // Przetwarzanie danych wynikowych } Jak widaè, proces jest doĈè zawiäy. Na szczöĈcie jQuery udostöpnia o wiele bardziej zwiözäe API do niego: jQuery.getJSON( http://przyklad.com/dane.json?callback=? , function(result){ // Przetwarzanie danych wynikowych }); Biblioteka jQuery zastñpi ostatni znak zapytania w powyĔszym adresie URL losowñ nazwñ utworzonej tymczasowej funkcji. Serwer bödzie musiaä natomiast odczytywaè parametr callback i uĔywaè go w roli nazwy zwracanej funkcji opakowujñcej. Bezpieczeħstwo Ŝédaħ miýdzy domenami JeĔeli posiadany serwer jest udostöpniany dla Ĕñdaþ JSONP z róĔnych domen, trzeba do- gäöbnie przemyĈleè kwestiö jego zabezpieczenia. Zazwyczaj zasada wspóäuĔytkowania zaso- bów miödzy domenami uniemoĔliwia potencjalnemu napastnikowi na przykäad wywoäanie API Twittera i pobranie osobistych danych innych uĔytkowników. Wszystko zmienia siö jed- nak w przypadku zastosowania CORS i JSONP. Podobnie jak w przypadku zwykäego Ĕñdania Ajax, wszystkie cookie sesji sñ przekazywane w ramach Ĕñdania, co oznacza, Ĕe zalogowanie do API Twittera juĔ siö dokonaäo. Potencjalny napastnik bödzie wiöc mógä przejñè peänñ kontrolö nad kontem, a to przesñdza sprawö — bezpieczeþstwo wymaga najwyĔszej uwagi. JeĔeli zatem nie moĔna z góry ograniczyè zbioru domen, które bödñ korzystaè z API i planuje siö uĔyè technologii CORS/JSONP, naleĔy zastosowaè siö do nastöpujñcych wytycznych: x Nie naleĔy ujawniaè Ĕadnych poufnych danych, takich jak adresy poczty elektronicznej. x Nie moĔna zezwalaè na wywoäanie jakichkolwiek akcji (jak na przykäad „follow” na Twitterze). Aby zapewniè odpowiedni poziom bezpieczeþstwa, moĔna takĔe z góry wyznaczyè okreĈlone domeny, które bödñ mogäy korzystaè z API, lub uĔyè uwierzytelnienia OAuth. Ĥadowanie danych _ 59 Wypeĥnienie ORM danymi Wypeänienie 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() bödzie iterowaè przez kolejne przekazane do niej wartoĈci 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 moĔna juĔ uĔyè 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ö dostöpne w bibliotece ORM. Przechowywanie danych lokalnie W przeszäoĈci przechowywanie danych na lokalnym komputerze byäo ogromnym wyzwa- niem. Jedynym dostöpnym rozwiñzaniem byäo wykorzystanie plików cookie oraz moduäów rozszerzajñcych, takich jak Adobe Flash. Cookie majñ przestarzaäe API, nie mogñ przecho- wywaè zbyt duĔej iloĈci danych, a wszystkie znajdujñce siö w nich dane sñ przesyäane do serwera wraz z kaĔdym Ĕñdaniem, co niepotrzebnie zwiöksza transfer. JeĈli zaĈ chodzi o Flash, wystarczy powiedzieè, Ĕe najlepiej trzymaè siö z dala od wszystkich moduäów rozszerzajñcych. Na szczöĈcie mechanizm przechowywania danych lokalnie zawarto w specyfikacji HTML5 i jest on obsäugiwany przez wiökszoĈè wspóäczesnych przeglñdarek. W odróĔnieniu od cookies dane sñ w tym przypadku przechowywane wyäñcznie po stronie klienta i nigdy nie sñ prze- syäane na serwery. IloĈè danych, które moĔna w ten sposób przechowywaè, jest takĔe niepo- równanie wiöksza, a maksymalny dozwolony wolumen zaleĔy od przeglñdarki (oraz jej wersji, zgodnie z listñ poniĔej); 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 skäada siö z dwóch elementów: przechowywania lokalnie (ang. local storage) oraz przechowywania w sesji (ang. session storage). Dane przechowywane 60 _ Rozdziaĥ 3. Modele i dane lokalnie zostajñ utrzymane równieĔ po zamkniöciu przeglñdarki, natomiast dane przecho- wywane w sesji sñ dostöpne wyäñcznie do czasu zamkniöcia okna. Wszystkie dane sñ prze- chowywane w kontekĈcie ich domeny i udostöpniane wyäñcznie tym skryptom, które pocho- dzñ z domen stanowiñcych Ēródäo tych danych. Aby skorzystaè z mechanizmów przechowywania danych lokalnie i przechowywania danych w sesji, naleĔy uĔyè odpowiednio obiektu localStorage oraz sessionStorage. Odpowiednie API jest bardzo podobne do w dziaäaniu do mechanizmu ustawiania wäaĈciwoĈci na obiektach JavaScriptu i, jeĈli nie liczyè róĔnic w nazwach obydwóch wspomnianych obiektów, jest iden- tyczne dla obydwóch mechanizmów: // Ustawienie wartoĞci localStorage[ someData ] = wem ; API WebStorage udostöpnia jeszcze kilka innych funkcji: // Liczba przechowywanych elementów danych var itemsStored = localStorage.length; // Ustawienie danych localStorage.setItem( someData , wem ); // Pobranie danych, zwrócenie null, jeĞli dane są nieznane localStorage.getItem( someData ); //= wem ; // UsuniĊcie danych, zwrócenie null, jeĞli dane są nieznane localStorage.removeItem( someData ); // Wyczyszczenie wszystkich elementów danych localStorage.clear(); Dane sñ przechowywane w postaci ciñgów znaków, dlatego jeĈli konieczne bödzie zapisanie obiektów albo liczb caäkowitych, trzeba bödzie samodzielnie dokonaè odpowiednich prze- ksztaäceþ. Aby to zrobiè przy uĔyciu JSON, naleĔy zserializowaè obiekty do postaci JSON przed ich zapisaniem, natomiast w przypadku odczytywania obiektów — zdeserializowaè ciñgi znaków JSON: var object = {some: object }; // Serializacja i zapisanie obiektu localStorage.setItem( seriData , JSON.stringify(object)); // Zaáadowanie i deserializacja obiektu var result = JSON.parse(localStorage.getItem( seriData )); JeĔeli wolumen danych przekroczy dozwolony rozmiar (zwykle jest to 5 MB na jeden serwer Ēró- däowy), w momencie próby zapisania kolejnych danych zwrócony zostanie bäñd QUOTA_EXCEEDED_ERR. Dodanie mechanizmu przechowywania danych lokalnie do ORM Dodajmy do biblioteki ORM opcjö przechowywania danych na lokalnym komputerze, aby umoĔliwiè utrzymanie rekordów miödzy kolejnymi odĈwieĔeniami strony. Aby skorzystaè z obiektu localStorage, naleĔy zserializowaè rekordy do postaci ciñgu znaków JSON. Problem polega na tym, Ĕe obecnie zserializowane obiekty wyglñdajñ nastöpujñco: var json = JSON.stringify(Asset.init({name: foo })); json //= { parent :{ parent :{ prototype :{}}, records :[]}, name : foo } Dodanie mechanizmu przechowywania danych lokalnie do ORM _ 61 Trzeba wiöc pokryè mechanizm serializacji JSON dla naszych modeli. W tym celu najpierw ustalmy, które wäaĈciwoĈci trzeba zserializowaè. Do obiektu Model dodamy tablicö attributes, w której kaĔdy z modeli bödzie wskazywaä odpowiednie atrybuty przeznaczone do serializacji: Model.extend({ created: function(){ this.records = {}; this.attributes = []; } }); Asset.attributes = [ name , ext ]; PoniewaĔ kaĔdy model ma odmienne atrybuty, przez co modele nie mogñ wspóäuĔytkowaè tej samej tablicy attributes, wäaĈciwoĈci tej nie ustawia siö bezpoĈrednio 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 wartoĈci: 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 kaĔdego modelu moĔna juĔ zdefiniowaè tablicö atrybutów: Asset.attributes = [ name , ext ]; Wówczas funkcja attributes() bödzie zwracaè obiekt z odpowiednimi wäaĈciwoĈciami: 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 ciñg znaków JSON bödzie zawieraä prawidäowe wäaĈciwoĈci: var json = JSON.stringify(Asset.records); json //= { 7B2A9E8D... : { name : document , ext : .txt , id : 7B2A9E8D... } } Skoro serializacja JSON dziaäa bez zarzutu, dodanie obsäugi przechowywania danych lokal- nie do naszego modelu bödzie 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 wysäany do localStorage: var Model.LocalStorage = { saveLocal: function(name){ // Przeksztaácenie records w tablicĊ var result = []; 62 _ Rozdziaĥ 3. Modele i dane 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 pomysäem bödzie odczytywanie rekordów z lokalnego repozytorium w trakcie äadowania strony i ich zapisywanie, gdy strona bödzie zamykana. Zostawiam to jednak jako èwiczenie dla Czytelników. Przesyĥanie nowych rekordów na serwer Nieco wczeĈniej w tej ksiñĔce pokazano, jak wykorzystywaè funkcjö post() biblioteki jQuery, aby przesyäaè dane do serwera. Funkcja przyjmuje trzy argumenty: docelowy adres URL, dane Ĕñdania i wywoäanie zwrotne: jQuery.post( /users , {first_name: Alex }, function(result){ /* ĩądanie POST Ajax zakoĔczyáo sie powodzeniem */ }); Dziöki wczeĈniejszemu zaimplementowaniu funkcji attributes() tworzenie rekordów na ser- werze jest juĔ proste — wystarczy metodñ POST przesäaè atrybuty rekordu: jQuery.post( /assets , asset.attributes(), function(result){ /* ĩądanie POST Ajax zakoĔczyáo sie powodzeniem */ }); Aby konsekwentnie trzymaè siö konwencji REST, w momencie tworzenia rekordu naleĔy 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 bödñ odpowiadaè za wysäanie 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, jeĈli na instancji zasobu Asset zostaje wywoäana funkcja createRemote(), atrybuty in- stancji sñ przesyäane do serwera metodñ POST: // Sposób uĪycia: Asset.init({name: jason.txt }).createRemote( /assets ); Przesyĥanie nowych rekordów na serwer _ 63 64 _ Rozdziaĥ 3. Modele i dane Skorowidz B Backbone, 179 aplikacja, 192 delegowanie zdarzeþ, 184 kolekcje, 181 komunikacja z serwerem, 188 kontrolery, 186 modele, 180 obsäuga historii, 187 wiñzanie, 185 widoki, 183 barwa, hue, 236 bezpieczeþstwo, 98, 115 bezpieczeþstwo Ĕñ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 audyt strony internetowej, 155 audytory, 155 automat skoþczony, 74 automatyczna aktualizacja widoku, 88 255 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 wydajnoĈci sieci WWW, 156 Ĕñdaþ sieciowych, 144 anulowanie zdarzeþ, 101 API, 33 Ajax, 226 biblioteki jQuery, 39, 55, 221 biblioteki Spine, 171 do obsäugi 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 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 testujñce, 129 zdarzeþ, 39 bäödy 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 wygaĈniöcia zasobu, 151 debugger JavaScriptu, 140, 143 definiowanie cieni, 238 deklarowanie moduäu, 90 delegowanie, 29 delegowanie zdarzeþ, 40, 72, 168, 184 däugotrwaäe poäñczenie, long polling, 113 dodawanie dziedziczenia, 26 funkcji, 23 funkcji prywatnych, 31 kontekstu, 67 metod, 24 przezroczystoĈci, 237 wäaĈciwoĈci, 24 wäaĈciwoĈci instancji, 33 wäaĈciwoĈci klasy, 33 256 _ Skorowidz dokumentacja jQuery, 225 dokumentacja LABjs, 96 DOM, 39 domenowy jözyk skryptowy DSL, 132 dostöp do plików, 97, 99 dostöp 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 usäug, 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 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 obsäugi szablonów, 84 pomocnicze aplikacji, 84 pomocnicze konsoli, 142 porównujñce, 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 przeglñdarki, 79 HJS, 32 Holla, 15, 120 HTML5, 97 I Ichabod, 136 identyfikator ID, 52 implementowanie sterownika, 131 Skorowidz _ 257 informacje o pliku, 101, 109 inkapsulacja zasiögu, 21 inspektory, 138 instalacja Spine, 157 interfejs kanaäowy, 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 obsäuga 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 258 _ Skorowidz aplikacji, 65 App, 178 Contacts, 175 Sidebar, 173 count, 203 limit, 203 offset, 203 kontrolka do przesyäania plików, 98 kontrolki stronicowania 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 kontrolowanie zasiögu, 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 moduäu, 92 plików na serwer, 107 równolegäe, 96 synchroniczne moduäów, 91 szablonów, 85 widoku, 212 äaþcuchy wywoäaþ, 227 äñczenie moduäów, 95 M manipulowanie modelem DOM, 223 maszyna stanów, 45, 74 metoda alert(), 138 DELETE, 207 GET, 207 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 wartoĈci domyĈlne, 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 moduäy, 89 modyfikatory jQuery, 211 MVC, Model View Controller, 18, 85, 180 N nagäówek Expires, 150 Last-Modified, 152 protokoäu HTTP, 114 nagrywanie sesji, 132 narzödzie 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 narzödzie do przesyäania plików, 98 nasäuch zdarzenia click, 21 nasäuchiwanie zdarzeþ, 218 nasycenie, saturation, 236 natywna implementacja klas, 22 natywna obsäuga klas, 32 natywny inspektor kodu, 140 nazwy funkcji konstruktorów, 22 negacja selektorów, 242 negocjowanie poäñczeþ 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 obsäuga IE6, 235 moduäów, 25 przeciñgania, 100 przejĈè, 242 szablonów, 211 szablonów HTML, 195 wywoäaþ zwrotnych, 25 zdarzeþ, 161 obszar upuszczania, 111 odpytywanie ciñgäe serwera, 113 opakowywanie moduäów, 94 opcje nagäówka, 151 max-age, 151 must-revalidate, 151 Skorowidz _ 259 no-store, 151 public, 151 operator new, 22 not, 242 this, 225 var, 31 ORM, 45, 48, 52 P pamiöè podröczna, 150 pasek postöpu, 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 poäñczenia wss, 117 poäñczenie zdublowane, 115 prödkoĈè dziaäania, 121 prödkoĈè 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 przeciñganie, 100 plików poza przeglñdarkö, 101 tekstu, 100 przedrostki stylów, 236 przeglñdarka Chrome, 123, 235 Firefox, 123, 235 IE, 123, 235 Opera, 123 Safari, 123, 235 przejĈcia, 242 przekierowanie robota, 78 staäe, 78 tymczasowe, 78 260 _ Skorowidz przepäyw zdarzeþ, 19 przestrzeþ nazw, 20, 89 przesyäanie plików, 108, 111 przetwarzanie plików, 97 przezroczystoĈè, 236 punkt przerwania, 143 Pusher, 119 QUnit, 126 Q R Rack, 119 Rack and Rails, 96 reguäy zagnieĔdĔone, 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 treĈci, 154 silnik generowania stron WWW, 235 silnik WebKit, 103 skäadnia stylów CSS3, 254 säowo 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 kontrolery, 166 modele, 161 proxied, 167 wäaĈciwoĈè 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 wstöpne, 213 Micro, 211 pakowanie, 213 Tmpl, 211 Ĉrodowisko testowe, 126 Ļ T tabela zgodnoĈci 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 niezaleĔne, 134 rozproszone, 137 testy Jasmine, 131 JavaScript, 131 jednostkowe, 125 QUnit, 128 täo, 241 tooltip, 215 Tornado, 119 transformacje, 244 Transport C, 92 Transport D, 92 tworzenie asercji, 130 biblioteki Growl, 228 gniazdka, 115 graficznych interfejsów uĔytkownika, 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 ukäadu, 250 widoków, 81 widĔetów, 219 typ atrybutów, 209 MIME, 56 zwracanych danych, 105 typy zdarzeþ, 37 U ukrywanie zakäadek, 42 upuszczanie, 101 usäuga REST, 207 ustawianie wartoĈci, setters, 205 utrzymywanie rekordów, 51 W W3C, 35 warstwa abstrakcji, 121, 180 warstwa abstrakcji dla zdarzenia, 100 Watir, 131 wczytywanie pliku, 105 wdraĔenie aplikacji internetowej, 149 Web Inspector, 138, 145 WebKit, 235 Skorowidz _ 261 WebSockets, 114 Web-sockets-js, 116 weryfikacja poprawnoĈci, 164 wiadomoĈci Message, 120 wiñzanie, 86 modeli, 87 zdarzeþ, 216 widok, 20 AppView, 195 TodoView, 195 widoki, 183 widĔet dymku z poradñ, 214 listy, 215 nextPrev, 214 witryna Mozilla Developer, 55 wklejanie, 104 wäasne przyciski przeglñdarki, 107 wywoäanie zwrotne, 86 zdarzenia, 168 znaczniki skryptów, 85 wäasny protokóä, 116 wäaĈciwoĈci, 24 ORM, 50 zdarzeþ, 38 wäaĈciwoĈè elements, 167 wplatanie danych, 55 wplecenia, 232 wyciekanie pamiöci, 214 wydajnoĈè aplikacji, 90, 94, 114, 149 wydzielanie biblioteki, 68 wykrywanie WebSockets, 115 wypeänianie kolekcji, 189 wywoäanie zwrotne, 45 wywoäywanie funkcji, 27 wywoäywanie metody bazowej, 201 wzorzec Element, 170 Module, 228 moduäu, 66 MVC, 47, 180 Publish/Subscribe, 43 PubSub, 119, 120 Render, 170 X XHR, 92 XMLHttpRequest, 108, 226 262 _ Skorowidz Yabble, 92 Y Z zadanie CRUD pobieranie, 208 tworzenie, 208 uaktualnianie, 209 usuwanie, 209 zamykanie poäñczenia, 116 zarzñdzanie oczekiwaniami, expec
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

JavaScript. Aplikacje WWW
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: