Web development Receptury nowej generacji twstnr

background image
background image

Tytuł oryginału: Web Development Recipes
Tłumaczenie: Łukasz Piwko

ISBN: 978-83-246-5149-8

© Helion 2013.
All rights reserved.

Copyright © 2012 The Pragmatic Programmers, LLC.
All rights reserved.

No part of this publication may be reproduced, stored in a retrieval system, or transmitted,
in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise,
without the prior consent of the publisher.

Many of the designations used by manufacturers and sellers to distinguish their products are claimed
as trademarks. Where those designations appear in this book, and The Pragmatic Programmers, LLC
was aware of a trademark claim, the designations have been printed in initial capital letters or in all
capitals. The Pragmatic Starter Kit, The Pragmatic Programmer, Pragmatic Programming, Pragmatic
Bookshelf, PragProg and the linking g device are trademarks of The Pragmatic Programmers, LLC.

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.
Materiały graficzne na okładce zostały wykorzystane za zgodą iStockPhoto Inc.

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/twstnr.zip

Drogi Czytelniku!
Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres
http://helion.pl/user/opinie/twstnr
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ść

background image

Spis treci

Podzikowania ..............................................................................................7

Wstp ...........................................................................................................11

Rozdzia 1. wiecideka ..............................................................................17

Receptura 1. Stylizowanie przycisków i czy ...........................................................17

Receptura 2. Stylizowanie cytatów przy uyciu CSS ................................................21

Receptura 3. Tworzenie animacji przy uyciu transformacji CSS3 ............................28

Receptura 4. Tworzenie interaktywnych pokazów slajdów przy uyciu jQuery ............33

Receptura 5. Tworzenie i stylizowanie wewntrztekstowych okienek pomocy ..............38

Rozdzia 2. Interfejs uytkownika ............................................................47

Receptura 6. Tworzenie szablonu wiadomoci e-mail ................................................47

Receptura 7. Wywietlanie treci na kartach .............................................................58

Receptura 8. Rozwijanie i zwijanie treci z zachowaniem zasad dostpnoci ...............65

Receptura 9. Nawigacja po stronie internetowej przy uyciu klawiatury ......................71

Receptura 10. Tworzenie szablonów HTML przy uyciu systemu Mustache ..............79

Receptura 11. Dzielenie treci na strony ....................................................................84

Receptura 12. Zapamitywanie stanu w Ajaksie ........................................................90

Receptura 13. Tworzenie interaktywnych interfejsów uytkownika

przy uyciu biblioteki Knockout.js .......................................................95

Receptura 14. Organizacja kodu przy uyciu biblioteki Backbone.js ..........................105

Rozdzia 3. Dane ........................................................................................123

Receptura 15. Wstawianie na stron mapy Google ...................................................123

Receptura 16. Tworzenie wykresów i grafów przy uyciu Highcharts ........................129

Receptura 17. Tworzenie prostego formularza kontaktowego ....................................137

Receptura 18. Pobieranie danych z innych serwisów przy uyciu formatu JSONP .....144

Kup książkę

Poleć książkę

background image

6

Web development. Receptury nowej generacji

Receptura 19. Tworzenie widetów do osadzenia w innych serwisach ........................147

Receptura 20. Budowanie witryny przy uyciu JavaScriptu i CouchDB .....................153

Rozdzia 4. Urzdzenia przenone ..........................................................163

Receptura 21. Dostosowywanie stron do wymogów urzdze przenonych .................163

Receptura 22. Menu rozwijane reagujce na dotyk ...................................................168

Receptura 23. Operacja „przecignij i upu” w urzdzeniach przenonych ...............171

Receptura 24. Tworzenie interfejsów przy uyciu biblioteki jQuery Mobile ................178

Receptura 25. Sprite’y w CSS ................................................................................187

Rozdzia 5. Przepyw pracy ......................................................................191

Receptura 26. Szybkie tworzenie interaktywnych prototypów stron ............................191

Receptura 27. Tworzenie prostego bloga przy uyciu biblioteki Jekyll ........................200

Receptura 28. Tworzenie modularnych arkuszy stylów przy uyciu Sass ....................207

Receptura 29. Bardziej przejrzysty kod JavaScript, czyli CoffeeScript ........................215

Receptura 30. Zarzdzanie plikami przy uyciu narzdzia Git ..................................222

Rozdzia 6. Testowanie ............................................................................233

Receptura 31. Debugowanie JavaScriptu .................................................................233

Receptura 32. ledzenie aktywnoci uytkowników przy uyciu map cieplnych ...........239

Receptura 33. Testowanie przegldarek przy uyciu Selenium ..................................242

Receptura 34. Testowanie stron internetowych przy uyciu Selenium i Cucumber ......247

Receptura 35. Testowanie kodu JavaScript przy uyciu Jasmine ................................260

Rozdzia 7. Hosting i wdraanie ..............................................................271

Receptura 36. Wspólna praca nad stron poprzez Dropbox ......................................271

Receptura 37. Tworzenie maszyny wirtualnej ...........................................................275

Receptura 38. Zmienianie konfiguracji serwera WWW przy uyciu programu Vim ......279

Receptura 39. Zabezpieczanie serwera Apache za pomoc SSL i HTTPS ..............284

Receptura 40. Zabezpieczanie treci .......................................................................288

Receptura 41. Przepisywanie adresów URL w celu zachowania czy .......................292

Receptura 42. Automatyzacja procesu wdraania statycznych serwisów

za pomoc Jammit i Rake .................................................................296

Dodatek A. Instalowanie jzyka Ruby ...................................................305

Dodatek B. Bibliografia ............................................................................309

Skorowidz ..................................................................................................311

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

79

Receptura 10.
Tworzenie szablonów HTML
przy uyciu systemu Mustache

Problem

Do utworzenia naprawd wyjtkowego interfejsu potrzebne jest zastosowanie
zarówno dynamicznych, jak i asynchronicznych technik programowania. Dziki
Ajaksowi i takim bibliotekom jak jQuery moemy modyfikowa interfejs uytkow-
nika bez zmieniania jego kodu HTML, poniewa potrzebne elementy dodamy
za pomoc JavaScriptu. Elementy te zazwyczaj dodaje si, stosujc technik
konkatenacji acuchów. Powstay w wyniku tego kod jest, niestety, zagmatwany
i atwo w nim popeni bd. Peno w nim mieszajcych si ze sob pojedynczych
i podwójnych cudzysowów oraz niekoczcych si acuchów wywoa metody

append()

z biblioteki jQuery.

Skadniki



jQuery



Mustache.js

Rozwizanie

Na szczcie, s nowoczesne narzdzia, takie jak Mustache, dziki którym moemy
pisa prawdziwy kod HTML, renderowa przy jego uyciu dane oraz wstawia
go do dokumentów. Mustache to system szablonów HTML dostpny w kilku
popularnych jzykach programowania. Implementacja JavaScript pozwala na
pisanie widoków dla klienta przy uyciu czystego kodu HTML cakowicie
oddzielonego od kodu JavaScript. Mona w nim uywa take instrukcji logicz-
nych i iteracji.

Mustache pozwala uproci tworzenie kodu HTML podczas generowania nowej
treci. Skadni tego narzdzia poznamy na przykadzie aplikacji JavaScript do
zarzdzania produktami.

Obecnie aplikacja ta umoliwia dodawanie nowych produktów do listy. Ponie-
wa wszystkie dania s obsugiwane przez JavaScript i Ajax, w przykadzie tym
uywamy naszego standardowego serwera roboczego. Gdy uytkownik wypeni
formularz dodawania nowego produktu, wysya do serwera danie zapisania

Kup książkę

Poleć książkę

background image

80

Web development. Receptury nowej generacji

tego produktu i wyrenderowania nowego produktu na licie. Aby doda produkt
do listy, musimy zastosowa konkatenacj acuchów, której kod jest zagmatwany
i nieelegancki:

mustache/submit.html
var newProduct = $('<li></li>');
newProduct.append('<span class="product-name">' +
product.name + '</span>');
newProduct.append('<em class="product-price">' +
product.price + '</em>');
newProduct.append('<div class="product-description">' +
product.description + '</div>');

productsList.append(newProduct);

Aby uy systemu Mustache.js, wystarczy go tylko zaadowa na stron. Jedn
z wersji tego pliku znajdziesz w pakiecie kodu towarzyszcym tej ksice, ale
moesz te pobra jego najnowsz wersj z serwisu GitHub

7

.

Renderowanie szablonu

Aby przerobi nasz istniejc aplikacj, przede wszystkim musimy dowiedzie
si, jak wyrenderowa szablon przy uyciu Mustache. Najprostszym sposobem na
zrobienie tego jest uycie funkcji

to_html()

.

Mustache.to_html(templateString, data);

Funkcja ta przyjmuje dwa argumenty. Pierwszy jest acuchem szablonowego kodu
HTML, w którym ma odbywa si renderowanie, a drugi to dane, które maj
zosta do tego szablonu wstawione. Zmienna

data

jest obiektem, którego klucze

w szablonie zostaj zamienione na lokalne zmienne. Spójrz na poniszy kod:

var artist = {name: "John Coltrane"};
var rendered = Mustache.to_html('<span class="artist name">{{ name }}</span>',
artist);
$('body').append(rendered);

Zmienna

rendered

zawiera nasz ostateczny kod HTML zwrócony przez metod

to_html()

. Aby umieci wasno

name

w naszym kodzie HTML, uylimy

znaczników Mustache ograniczonych podwójnymi klamrami. W klamrach tych
umieszcza si nazwy wasnoci. Ostatni wiersz kodu dodaje wyrenderowany kod
HTML do elementu

<body>

.

Jest to najprostsza technika renderowania szablonu przy uyciu Mustache.
W naszej aplikacji bdzie wicej kodu zwizanego z wysyaniem dania do serwera
w celu pobrania danych, ale proces tworzenia szablonu pozostanie bez zmian.

7

https://github.com/janl/mustache.js

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

81

Podmienianie istniejcego systemu

Skoro wiemy ju, jak si renderuje szablony, moemy z naszego programu usun
stary kod konkatenacji. Przyjrzymy mu si, aby zobaczy, co mona usun,
a co trzeba podmieni.

mustache/submit.html
function renderNewProduct() {
var productsList = $('#products-list');

var newProductForm = $('#new-product-form');

var product = {};
product.name = newProductForm.find('input[name*=name]').val();
product.price = newProductForm.find('input[name*=price]').val();
product.description =
newProductForm.find('textarea[name*=description]').val();

var newProduct = $('<li></li>');
newProduct.append('<span class="product-name">' +
product.name + '</span>');
newProduct.append('<em class="product-price">' +
product.price + '</em>');
newProduct.append('<div class="product-description">' +
product.description + '</div>');

productsList.append(newProduct);

productsList.find('input[type=text], textarea').each(function(input) {
input.attr('value', '');
});
}

Ten skomplikowany kod bardzo trudno jest rozszyfrowa, a jeszcze trudniej go
modyfikowa. Dlatego zamiast metody

append()

jQuery do budowy struktury

HTML uyjemy systemu Mustache. Moemy napisa prawdziwy kod HTML,
a nastpnie wyrenderowa dane przy uyciu Mustache! Pierwszym krokiem
w kierunku pozbycia si pltaniny JavaScriptu jest zbudowanie szablonu. Póniej
wyrenderujemy go wraz z danymi produktów w jednym prostym procesie.

Jeli utworzymy element

<script>

z typem treci

text/template

, to bdziemy mogli

w nim umieci kod HTML Mustache i pobiera go stamtd do szablonu.
Nadamy mu identyfikator, aby móc si do niego odwoywa z kodu jQuery.

<script type="text/template" id="product-template">
<!-- Szablon HTML -->
</script>

Nastpnie napiszemy kod HTML naszego szablonu. Mamy ju produkt w postaci
obiektu, a wic jego wasnoci w szablonie moemy uy jako nazw zmiennych:

Kup książkę

Poleć książkę

background image

82

Web development. Receptury nowej generacji

Ja pyta:

Czy mona uywa zewntrznych szablonów?

Szablony wewntrzne s porczne, ale my chcemy oddzieli logik szablo-
now od widoków serwera. Na serwerze naleaoby utworzy folder
do przechowywania wszystkich plików widoków. Nastpnie, gdy trzeba
wyrenderowa jeden z szablonów, pobieramy go za pomoc jQery
i dania

GET

.

$.get("http://mojastrona.com/js_views/zewnetrzny_szablon.html",
function(template) {
Mustache.to_html(template, data).appendTo("body");
}
);

W ten sposób mona serwowa widoki serwera osobno od widoków
klienta.

<script type="text/template" id="product-template">
<li>
<span
class="product-name">{{ name }}</span>
<em
class="product-price">{{ price }}</em>
<div class="product-description">{{ description }}</div>
</li>
</script>

Majc gotowy szablon, moemy wróci do poprzedniego kodu, aby zmieni sposób
wstawiania kodu HTML. Moemy pobra odwoanie do szablonu przy uyciu
jQuery i za pomoc metody

html()

pobra tre wewntrzn. Póniej trzeba

jeszcze tylko przesa kod HTML i dane do Mustache.

var newProduct = Mustache.to_html( $('#product-template').html(), product);

Wynik tego powinien by ju zadowalajcy, chocia gdy nie ma adnego opisu,
pole opisu nie powinno by widoczne. Innymi sowy, jeli nie ma opisu, nie
powinnimy renderowa jego elementu

<div>

. Na szczcie, w Mustache mona

uywa instrukcji warunkowych. Przy ich uyciu sprawdzimy, czy opis istnieje,
i jeli tak, to wyrenderujemy dla niego element

<div>

.

{{#description}}
<div class="product-description">{{ description }}</div>
{{/description}}

Przy uyciu tego samego operatora Mustache wykona iteracj po tablicy. System
sprawdzi, czy dana wasno jest tablic, i jeli tak, to automatycznie zastosuje
iteracj.

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

83

Stosowanie iteracji

Poniewa udao nam si wymieni znaczn cz istniejcego kodu budujcego
nowy produkt, postanowilimy, e wiksz cz logiki aplikacji napiszemy
w JavaScripcie. Zamienimy stron indeksow, na której wywietlane s produkty
wraz z uwagami, na kod JavaScript, który bdzie robi to samo. Utworzymy tablic
produktów na jednej z wasnoci obiektu danych i kady produkt w tej tablicy
bdzie mia wasno

notes

. Wasno

notes

bdzie tablic, po której iteracja bdzie

si odbywa wewntrz szablonu.

Najpierw pobierzemy i wyrenderujemy produkty. Przyjmujemy zaoenie, e ser-
wer zwraca tablic w formacie JSON wygldajc tak:

$.getJSON('/products.json', function(products) {
var data = {products: products};
var rendered = Mustache.to_html($('#products-template').html(), data);
$('body').append(rendered);
});

Teraz musimy zbudowa szablon do wyrenderowania produktów. W Mustache
iteracj po tablicy wykonuje si, przekazujc t tablic operatorowi

#

, np.

{{#zmienna}}

. Wewntrz iteracji wasnoci, które wywoujemy, znajduj si

w kontekcie obiektów w tablicy.

mustache/index.html
<script type="text/template" id="products-template">
{{#products}}
<li>
<span class="product-name">{{ name }}</span>
<em class="product-price">{{ price }}</em>
<div class="product-description">{{ description }}</div>
<ul class="product-notes">
{{#notes}}
<li>{{ text }}</li>
{{/notes}}
</ul>
</li>
{{/products}}
</script>

Teraz nasza strona indeksowa moe by w caoci generowana w przegldarce
przy uyciu szablonów i Mustache.

Szablony JavaScript s doskonaym narzdziem pozwalajcym dobrze zorgani-
zowa kod aplikacji JavaScript. Nauczye si renderowa szablony, uywa
instrukcji warunkowych oraz stosowa iteracj. Mustache.js jest prostym narz-
dziem pozwalajcym pozby si konkatenacji acuchów i budowa struktur
HTML w czytelny i zgodny z semantyk sposób.

Kup książkę

Poleć książkę

background image

84

Web development. Receptury nowej generacji

Kontynuacja

Szablony Mustache pozwalaj zachowa przejrzysto nie tylko kodu dziaajcego
po stronie klienta, ale równie serwerowego. Istniej implementacje tego systemu
w jzykach Ruby, Java, Python, ColdFusion i wielu innych. Wicej informacji
na ten temat mona znale na stronie Mustache

8

.

Mustache mona zatem uywa jako systemu szablonów zarówno przy budowie
frontu, jak i zaplecza aplikacji. Gdybymy na przykad mieli szablon Mustache
reprezentujcy wiersz tabeli HTML i uyli go wewntrz ptli budujcej tabel
przy wczytywaniu strony, to tego samego szablonu moglibymy te uy w celu
dodania wiersza do tej tabeli po udanym wykonaniu dania Ajax.

Zobacz równie



Receptura 11.: „Dzielenie treci na strony”



Receptura 13.: „Tworzenie interaktywnych interfejsów uytkownika
przy uyciu biblioteki Knockout.js”



Receptura 14.: „Organizacja kodu przy uyciu biblioteki Backbone.js”



Receptura 20.: „Budowanie witryny przy uyciu JavaScriptu
i CouchDB”

Receptura 11.
Dzielenie treci na strony

Problem

Aby zaoszczdzi uytkownikom nadmiaru treci na jednej stronie, a przy okazji
nie przeciy serwerów, naley ustali limit iloci danych, jaka moe zosta
wywietlona na jednej stronie. Najczciej w tym celu dodaje si mechanizm
dzielenia stron. Jego dziaanie polega na tym, e wywietlana jest tylko cz
zawartoci strony i uytkownik moe w razie potrzeby przejrze take pozostae
czci. Pocztkowo wywietlana jest tylko maa czstka tego, co mona obejrze.

W toku ewolucji stron internetowych ich twórcy spostrzegli, e uytkownicy
wikszo czasu spdzaj na przegldaniu treci w sposób liniowy. Najchtniej

8

http://mustache.github.com/

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

85

przegldaliby cae listy danych, a do znalezienia szukanych informacji albo
osignicia koca zbioru. Naszym zadaniem jest umoliwienie im takiego prze-
gldania i jednoczenie uniknicie przecienia serwera.

Skadniki



jQuery



Mustache.js

9



QEDServer

Rozwizanie

Paginacja to dobry sposób na zapanowanie nad zasobami, który dodatkowo ua-
twia korzystanie ze strony uytkownikowi. Zamiast zmusza uytkownika do
wybrania nastpnej strony wyników i wczytywa cay interfejs od nowa, nastpn
stron wczytujemy w tle i dodajemy j do biecej strony, podczas gdy uytkow-
nik zblia si do jej koca.

Chcemy umieci na stronie list naszych produktów, ale jest ich za duo, aby
wywietli je wszystkie naraz. Dlatego zastosujemy paginacj z ograniczeniem
polegajcym na wywietlaniu maksymalnie 10 produktów naraz. eby jeszcze
bardziej uatwi ycie uytkownikom, pozbdziemy si przycisku Nastpna strona
i zamiast tego bdziemy automatycznie wczytywa kolejne strony, gdy uznamy,
e naley to zrobi. Od strony uytkownika bdzie to wygldao tak, jakby caa
lista bya dostpna na stronie od samego pocztku.

Do budowy prototypu uyjemy QEDServera i jego katalogu produktów. Cay
kod ródowy umiecimy w folderze public w przestrzeni roboczej QEDServera.
Uruchom QEDServer i utwórz nowy plik o nazwie products.html w folderze
public utworzonym przez QEDServer. Jeli nie wiesz, czym jest QEDServer,
zajrzyj do „Wstpu”, w którym znajduje si objanienie.

Aby utrzyma porzdek w kodzie, uyjemy biblioteki szablonów Mustache,
o której bya mowa w recepturze 10., „Tworzenie szablonów HTML przy uyciu
systemu Mustache”. Pobierz t bibliotek i umie j take w folderze public.

Zaczniemy od utworzenia prostego szkieletu strony index.html w HTML5.
Doczymy do niej biblioteki jQuery, Mustache oraz plik endless_pagination.js,
który bdzie zawiera nasz kod paginacji.

9

http://github.com/documentcloud/underscore/blob/master/underscore.js

Kup książkę

Poleć książkę

background image

86

Web development. Receptury nowej generacji

endlesspagination/products.html
<!DOCTYPE html>
<html>
<head>
<meta
charset='utf-8'>
<title>Produkty AwesomeCo</title>
<link rel='stylesheet' href='endless_pagination.css'>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js">
</script>
<script
type="text/javascript" src="mustache.js"></script>
<script src="endless_pagination.js"></script>
</head>
<body>
<div
id="wrap">
<header>
<h1>
Produkty</h1>
</header>
</div>
</body>
</html>

W strukturze tej strony umiecilimy kontener na tre i obraz wirujcego kóka
widoczny na rysunku 2.8. Animacja ta ma na celu zasygnalizowa uytkownikowi,
e trwa wczytywanie nastpnej strony, które powinno si odbywa w tle.

endlesspagination/products.html
<div id='content'>
</div>
<img
src='spinner.gif' id='next_page_spinner'>

API QEDServer jest tak skonfigurowane, e zwraca stronicowane wyniki i reaguje
na dania JSON. Moemy si o tym przekona, otwierajc adres http://localhost:
8080/Products.json?page=2
.

Wiedzc, jakie informacje otrzymujemy od serwera, moemy rozpocz budow
kodu, który bdzie aktualizowa interfejs. W tym celu napiszemy funkcj pobiera-
jc tablic w formacie JSON, znakujc j przy uyciu szablonu Mustache
i wynik tego dziaania dodajc na kocu strony. Cay ten kod umiecimy w pliku
o nazwie endless_pagination.js. Zaczniemy od napisania funkcji pomocniczych.
Na pierwszy ogie pójdzie funkcja renderujca odpowied w formacie JSON do
HTML.

endlesspagination/endless_pagination.js
function loadData(data) {
$('#content').append(Mustache.to_html("{{#products}} \
<div class='product'> \
<a href='/products/{{id}}'>{{name}}</a> \
<br> \
<span class='description'>{{description}}</span> \
</div>{{/products}}
", { products: data }));
}

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

87

Rysunek 2.8.

Widok dolnej czci strony

W procesie iteracji szablon utworzy dla kadego produktu element

<div>

, w któ-

rym tre jest nazw produktu w postaci cza. Nastpnie nowe elementy zostan
dodane na kocu listy produktów i pojawi si na stronie.

Nastpnie, jako e po dotarciu przez uytkownika na koniec strony chcemy
wczyta kolejn stron, musimy znale sposób na okrelenie, czym jest ta nastpna
strona. W tym celu moemy przechowywa biec stron jako zmienn globaln,
a nastpnie gdy bdziemy gotowi — utworzy URL dla nastpnej strony.

endlesspagination/endless_pagination.js
var currentPage = 0;
function nextPageWithJSON() {
currentPage += 1;
var newURL = 'http://localhost:8080/products.json?page=' + currentPage;

var splitHref = document.URL.split('?');
var parameters = splitHref[1];

Kup książkę

Poleć książkę

background image

88

Web development. Receptury nowej generacji

if (parameters) {
parameters = parameters.replace(/[?&]page=[^&]*/, '');
newURL += '&' + parameters;
}
return newURL;
}

Funkcja

nextPageWithJSON()

zwiksza warto zmiennej

currentPage

i dodaje j

do biecego adresu jako warto parametru

page=

. Zapamitujemy te wszystkie

inne parametry znajdujce si w biecym URL. Jednoczenie upewniamy si,
e stary parametr

page

, jeli istnieje, zostanie nadpisany. Dziki temu otrzymamy

waciw odpowied od serwera.

Funkcje wywietlajce now tre i okrelajce adres nastpnej strony s ju
gotowe. Czas w takim razie napisa funkcj pobierajc tre z serwera. W istocie
funkcja ta bdzie po prostu daniem Ajax wysyanym do serwera. Musimy tylko
zaimplementowa w niej podstawowy mechanizm zapobiegajcy wysyaniu nie-
potrzebnych da. Utworzymy zmienn globaln o nazwie

loadingPage()

, któr

zainicjujemy wartoci

0

. Przed wykonaniem dania bdziemy j zwiksza,

a po jego zakoczeniu — zmniejsza z powrotem. Jest to co w rodzaju muteksu,
czyli mechanizmu blokujcego. Bez tej blokady do serwera wysyane byyby
dziesitki da, a serwer by na nie skwapliwie odpowiada, mimo e nie o to nam
chodzio.

endlesspagination/endless_pagination.js
var loadingPage = 0;
function getNextPage() {
if (loadingPage != 0) return;

loadingPage++;
$.getJSON(nextPageWithJSON(), {}, updateContent).
complete(function() { loadingPage-- });
}

function updateContent(response) {
loadData(response);
}

Po otrzymaniu odpowiedzi na danie Ajax przekazujemy j do funkcji

loadData()

,

której definicj przedstawiono wczeniej. Po dodaniu nowej treci przez funkcj

loadData()

aktualizujemy adres URL przechowywany w zmiennej

nextPage

. Jeste-

my gotowi na wykonanie kolejnego dania Ajax.

Majc funkcj dajc nastpnej strony, teraz musimy zaj si sprawdzaniem,
czy uytkownik w ogóle jest gotowy na wczytanie kolejnej strony. Normalnie
wywietlilibymy po prostu cze Nastpna strona, ale nam chodzi o co innego.
Potrzebujemy funkcji, która bdzie zwraca

true

, gdy dolna krawd okna prze-

gldarki znajdzie si w okrelonej odlegoci od dou strony.

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

89

endlesspagination/endless_pagination.js
function readyForNextPage() {
if (!$('#next_page_spinner').is(':visible')) return;

var threshold = 200;
var bottomPosition = $(window).scrollTop() + $(window).height();
var distanceFromBottom = $(document).height() - bottomPosition;

return distanceFromBottom <= threshold;
}

Na koniec dodajemy procedur obsugi zdarzenia przewijania kókiem myszy,
która wywouje funkcj

observeScroll()

. Gdy uytkownik przewinie stron za

pomoc kóka myszy, nastpi wywoanie funkcji pomocniczej

readyForNextPage()

.

Gdy funkcja ta zwróci

true

, wywoamy funkcj

getNextPage()

, aby wykona da-

nie Ajax.

endlesspagination/endless_pagination.js
function observeScroll(event) {
if (readyForNextPage()) getNextPage();
}

$(document).scroll(observeScroll);

Cz dotyczc „nieskoczonego wywietlania treci” mamy za sob, ale przecie
kiedy ta nasza tre jednak si skoczy. Po wywietleniu ostatniego produktu
wirujce kóko powinno zosta ukryte, poniewa jeli bdzie widoczne, uytkow-
nik pomyli, e albo co jest nie tak z jego czem internetowym, albo z nasz
stron. Aby usun wirujce kóko, dodamy test, który bdzie powodowa jego
ukrycie, gdy serwer zwróci pust list.

endlesspagination/endless_pagination.js
function loadData(data) {
$('#content').append(Mustache.to_html("{{#products}} \
<div class='product'> \
<a href='/products/{{id}}'>{{name}}</a> \
<br> \
<span class='description'>{{description}}</span> \
</div>{{/products}}
", { products: data }));
if (data.length == 0) $('#next_page_spinner').hide();
}

To wszystko. Gdy dotrzemy do koca listy, wirujce kóko zniknie.

Kontynuacja

Opisana tu technika jest doskona metod wywietlania dugich list danych
w sposób zgodny z oczekiwaniami uytkowników. Dziki podziaowi rozwizania
na funkcje atwo je bdzie przystosowa do rónych projektów. Mona zmieni

Kup książkę

Poleć książkę

background image

90

Web development. Receptury nowej generacji

Funkcjonalno przegldarki IE 8

W przegldarce IE 8 ten kod nie dziaa. Przegldarka ta wymaga, aby
nagówki da JSON byy w bardzo specyficznym formacie, np. strona
kodowa UTF-8 musi zosta wysana jako utf8. Bez poprawnych nagówków
danie Ajax nie powiedzie si i na stronie bdzie wywietlone tylko wiru-
jce kóko. Naley o tym pamita podczas pracy z formatem JSON na ser-
werze i w przegldarce IE.

warto zmiennej

treshold

, aby tre bya wczytywana wczeniej lub póniej, lub

zmodyfikowa funkcj

loadData()

, aby zwracaa odpowied w formacie HTML

lub XML zamiast JSON. A najlepsze jest to, e moemy by spokojni o dostp-
no naszej strony take wówczas, gdy z jakiego powodu biblioteka jQuery nie
bdzie obsugiwana. Moesz to sprawdzi, wyczajc JavaScript w swojej prze-
gldarce.

W nastpnej recepturze pokaemy Ci, jak ulepszy ten kod poprzez dodanie
obsugi zmian adresu URL i przycisku Wstecz.

Zobacz równie



Receptura 12.: „Zapamitywanie stanu w Ajaksie”



Receptura 10.: „Tworzenie szablonów HTML przy uyciu systemu
Mustache”

Receptura 12.
Zapamitywanie stanu w Ajaksie

Problem

Jedn z najwikszych zalet internetu jest moliwo dzielenia si odnonikami
z innymi ludmi. Jednak wraz z nadejciem ery Ajaksa nie wszystko jest takie
proste. Klikajc cze Ajax, nie mamy gwarancji, e spowoduje to zmian adresu
URL w pasku przegldarki. To nie tylko utrudnia wymian odnonikami z innymi
ludmi, ale równie powoduje wadliwe dziaanie przycisku Wstecz przegldarki.
Strony zawierajce takie cza nie s dobrymi obywatelami internetu, poniewa
gdy si je wyczy, nie da si wróci bezporednio do poprzedniego stanu.

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

91

Niestety, skrypt paginacji, który napisalimy w recepturze 11., „Dzielenie treci
na strony”, równie nie naley do wzorowych obywateli. Gdy uytkownik prze-
wija stron i przechodzi do kolejnych porcji informacji, adres URL cay czas
pozostaje taki sam. A przecie kade wczytanie oznacza nowy stan, w którym
prezentowane s inne dane ni bezporednio po wczytaniu strony. Gdyby
na przykad spodoba si nam produkt ze strony pitej i wysalibymy znajomemu
odnonik do niej, znajomy ten mógby nie znale tego, o czym mu pisalimy,
poniewa zobaczyby inn list ni my.

To nie wszystko. Gdy uytkownik kliknie przycisk Wstecz przegldarki na stro-
nie zbudowanej w caoci na bazie Ajaksa, to nie przejdzie tam, gdzie by chcia,
tylko na poprzedni stron, z której trafi do nas. Zdziwiony kliknie przycisk Dalej
i pogubi si cakowicie. Na szczcie, znamy rozwizanie tych problemów.

Skadniki



jQuery



Mustache.js

10



QEDServer

Rozwizanie

W tej recepturze dokoczymy prac rozpoczt w recepturze 11., „Dzielenie
treci na strony”. Mimo i zastosowana tam metoda ogólnie dziaa, to jednak ma
t wad, e uniemoliwia odwiedzajcym dzielenie si linkami do stron. Aby
speni wymogi dobrego projektowania stron i nie utrudnia ycia uytkowni-
kom, musimy sprawi, aby nasza lista produktów ledzia swój stan. Innymi
sowy, gdy zmieni si strona, na któr patrzymy, wraz z ni powinien zmienia si
adres URL. W specyfikacji HTML5 wprowadzono funkcj JavaScript o nazwie

pushState()

, która w wikszoci przegldarek pozwala na zmian adresu URL

bez opuszczania strony. To doskonaa wiadomo dla programistów stron inter-
netowych! Dziki temu moemy napisa stron w caoci opart na Ajaksie,
której przegldanie nigdy nie wymaga wykonywania caego cyklu da i przea-
dowa. Oznacza to, e nie musimy ju wczytywa takich zasobów, jak nagówek
i stopka dokumentu, wysya w nieskoczono da plików graficznych, arkuszy
stylów i skryptów JavaScript za kadym razem, gdy przechodzimy na now stron

10

http://github.com/documentcloud/underscore/blob/master/underscore.js

Kup książkę

Poleć książkę

background image

92

Web development. Receptury nowej generacji

w obrbie witryny. A uytkownicy mog bez problemu przesya linki znajomym
i nigdy si nie pogubi, w którym miejscu w serwisie aktualnie si znajduj. Naj-
lepsze jest to, e przycisk Wstecz przegldarki równie bdzie dziaa poprawnie.

Funkcja pushState()

Funkcja

pushState()

jest jeszcze dopracowywana. Wikszo starych przeglda-

rek jej nie obsuguje, ale istniej rozwizania awaryjne wykorzystujce cz adresu
URL za znakiem

#

. Rozwizania te moe nie s eleganckie, ale dziaaj. Poza

tym nie chodzi tylko o pikne adresy URL. Internet ma bardzo dobr pami
dugotrwa. Stworzono go nie tylko do zabawy i pogaduszek, lecz równie po
to, aby mona byo nawet po latach znale stare strony, do których kiedy utwo-
rzyo si cze, a które zostay przeniesione na nowy serwer (pod warunkiem
e ich twórcy s dobrymi obywatelami internetu i stosuj poprawne przekierowa-
nia HTTP 301). Jeli bdziemy uywa znaku # w adresach URL jako tym-
czasowego rozwizania dla wanych informacji, to moe si okaza, e nigdy si
ich nie pozbdziemy

11

. Poniewa znaki # z adresów URL nigdy nie s wysyane

do serwera, nasza aplikacja musiaaby dalej przekierowywa ruch po tym, gdy
funkcja

pushState()

stanie si standardem.

Uzbrojeni w t now wiedz, zobaczmy, co trzeba zrobi, aby nasza niekoczca
si strona z produktami uzyskaa wiadomo swojego stanu.

Parametry, które trzeba ledzi

Poniewa nie wiemy, na któr stron uytkownik wejdzie za pierwszym razem,
bdziemy ledzi zarówno stron startow, jak i biec. Jeli uytkownik wejdzie
od razu na trzeci stron, to chcemy, aby przy kolejnych wizytach móg na ni
wróci. Jeli odwiedzajcy skorzysta z kóka myszy na stronie trzeciej i wczyta
kilka kolejnych stron, np. do strony siódmej, to równie chcemy o tym wiedzie.
Potrzebujemy sposobu na zapamitanie strony startowej i kocowej, aby w przy-
padku odwieenia uytkownik nie musia przewija wszystkiego od pocztku.

Musimy te znale sposób na wysyanie startowej i kocowej strony z klienta.
Najbardziej oczywistym rozwizaniem w tym przypadku wydaje si dodanie tych
parametrów do adresu URL w daniu

GET

. Przy pierwszym wczytaniu strony

ustawimy parametr

page

adresu na biec stron i przyjmiemy zaoenie, e

uytkownik chce obejrze tylko t stron. Gdy klient przekae dodatkowo para-
metr

start_page

, bdziemy wiedzie, e uytkownik chce obejrze kilka stron, od

11

http://danwebb.net/2011/5/28/it-is-about-the-hashbangs

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

93

start_page

do

page

. Wracajc do poprzedniego przykadu, gdybymy byli na

stronie siódmej, ale zaczli przegldanie od strony trzeciej, to nasz adres URL
wygldaby nastpujco http://localhost:8080/products?start_page=3&page=7.

Te parametry powinny nam wystarczy do odtworzenia listy produktów i po-
kazania uytkownikowi takiej samej strony za kadym razem.

statefulpagination/stateful_pagination.js
function getParameterByName(name) {
var match = RegExp('[?&]' + name + '=([^&]*)')
.exec(window.location.search);

return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}

var currentPage = 0;
var startPage = 0;

$(function() {
startPage = parseInt(getParameterByName('start_page'));
if (isNaN(startPage)) {
startPage = parseInt(getParameterByName('page'));
}
if (isNaN(startPage)) {
startPage = 1;
}
currentPage = startPage - 1;

if (getParameterByName('page')) {
endPage = parseInt(getParameterByName('page'));
for (i = currentPage; i < endPage; i++) {
getNextPage(true);
}
}

observeScroll();
});

Skrypt ten sprawdza parametry

start_page

i

page

, a nastpnie wysya danie

odpowiednich stron do serwera. Uylimy funkcji bardzo podobnej do

getNext

´

Page()

z poprzedniej receptury, tylko z obsug wielu da naraz. W odró-

nieniu od sytuacji, gdy uytkownik korzysta z kóka myszy i chcemy zapobiec
nakadaniu si da, w tym przypadku nie przeszkadza nam to, poniewa wiemy
dokadnie, których stron ma dotyczy danie.

Podobnie jak ledzilimy wczeniej warto zmiennej

currentPage

, teraz bdziemy

ledzi

startPage

. Parametr ten bdziemy pobiera z adresu URL, dziki czemu

bdziemy mogli wykonywa dania stron, które nie byy jeszcze wczytywane.
Liczba ta nie bdzie si zmienia, ale musi by dodawana do adresu URL i by
w nim przy kadym daniu nowej strony.

Kup książkę

Poleć książkę

background image

94

Web development. Receptury nowej generacji

Aktualizowanie adresu URL w przegldarce

Do aktualizacji adresu URL w przegldarce napiszemy funkcj o nazwie

update

´

BrowserUrl()

, wywoujc funkcj

pushState()

oraz ustawiajc parametry

start_

´

page

i

page

. Naley przy okazji pamita, e nie wszystkie przegldarki obsu-

guj funkcj

pushState()

, i przed jej wywoaniem sprawdza, czy jest zdefinio-

wana. W tych przegldarkach nasze rozwizanie po prostu nie bdzie dziaa, ale
powinnimy przygotowywa nasze aplikacje z myl o przyszoci.

statefulpagination/stateful_pagination.js
function updateBrowserUrl() {
if (window.history.pushState == undefined) return;

var newURL = '?start_page=' + startPage + '&page=' + currentPage;
window.history.pushState({}, '', newURL);
}

Funkcja

pushState()

przyjmuje trzy parametry. Pierwszy jest obiekt stanu, który

jest w istocie obiektem w formacie JSON. Argument ten moglibymy wykorzysta
do przechowywania informacji dotyczcych stanu, poniewa w wyniku przewija-
nia od serwera otrzymujemy dane wanie w formacie JSON. Poniewa jednak
nasze dane s proste i atwe do pobrania z serwera, wydaje si, e nie jest to warte
zachodu. Drugi argument to tytu nowego stanu. Nie jest on na razie szeroko
obsugiwany przez przegldarki, ale w naszym przypadku to nie problem, bo
i tak bymy tego nie potrzebowali. W zwizku z tym przekazujemy w nim pusty
acuch.

W kocu dochodzimy do najwaniejszego elementu funkcji

pushState()

. Trzeci

parametr okrela, co ma si zmieni w adresie. Moe to by zarówno bezwzgldna
cieka, jak i zestaw parametrów, które maj zosta zmienione na kocu adresu.
Ze wzgldów bezpieczestwa nie mona zmienia domeny, ale wszystko, co
znajduje si za ni — tak. Poniewa nas interesuje tylko zmienianie parametrów
adresu URL, na pocztku trzeciego parametru funkcji

pushState()

wpisalimy

znak

?

. Nastpnie wpisalimy ustawienia parametrów

start_page

i

page

. Jeli

parametry te bd znajdowa si w adresie, funkcja sama je zaktualizuje.

statefulpagination/stateful_pagination.js
function updateContent(response) {
loadData(response);
updateBrowserUrl();
}

Na koniec, aby nasz mechanizm paginacji zacz rozpoznawa swój stan, doda-
limy wywoanie funkcji

updateBrowserUrl()

do funkcji

updateContent()

. Od tej pory

uytkownicy mog bez przeszkód uywa przycisku Wstecz, aby wyj ze strony,
i przycisku Dalej, aby na ni wróci do tego samego miejsca. Take odwieenie

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

95

strony niczego nie zepsuje. Co jednak najwaniejsze, teraz odwiedzajcy mog
wysya znajomym linki do naszych stron. Dziki cikiej pracy programistów
przegldarek internetowych udao nam si sprawi, aby nasza strona indeksowa
bya dobrym obywatelem internetu.

Kontynuacja

Dodajc kolejne skrypty JavaScript i Ajax do swoich stron, powinnimy mie
wiadomo dziaania uywanych interfejsów. Metoda

pushState()

HTML5

i API History pozwalaj nam przywróci normalne dziaanie kontrolek, do któ-
rych uytkownicy s przyzwyczajeni. Warstwy abstrakcji, takie jak History.js

12

,

jeszcze to uatwiaj, poniewa dostarczaj eleganckich rozwiza awaryjnych
dla starych przegldarek.

Opisane przez nas rozwizania zaczynaj te by implementowane w bibliotekach
JavaScript, jak np. Backbone.js, co oznacza, e moemy spodziewa si jeszcze
lepszej obsugi przycisku Wstecz nawet na najbardziej skomplikowanych jedno-
stronicowych aplikacjach.

Zobacz równie



Receptura 10.: „Tworzenie szablonów HTML przy uyciu systemu
Mustache”



Receptura 14.: „Organizacja kodu przy uyciu biblioteki Backbone.js”

Receptura 13.
Tworzenie interaktywnych
interfejsów uytkownika
przy uyciu biblioteki Knockout.js

Problem

Programujc nowoczesne aplikacje sieciowe, staramy si, aby w reakcji na dzia-
ania uytkownika aktualizowana bya jak najmniejsza cz interfejsu. Odwoania
do serwera s zawsze czasochonne, a odwieanie caej strony moe spowodowa
zniechcenie uytkownika.

12

http://plugins.jquery.com/plugin-tags/pushstate

Kup książkę

Poleć książkę

background image

96

Web development. Receptury nowej generacji

Niestety, kod JavaScript uywany do implementacji tych mechanizmów czsto
szybko wymyka si spod kontroli. Na pocztku obserwowanych jest tylko kilka
zdarze, ale z czasem dodajemy kolejne funkcje zwrotne do aktualizowania ró-
nych obszarów strony i utrzymanie tego wszystkiego w ryzach staje si bardzo
kopotliwe.

Knockout to prosta, a zarazem bardzo funkcjonalna biblioteka, pozwalajca wi-
za obiekty z interfejsem i automatycznie aktualizowa jedn cz interfejsu,
podczas gdy zmieniana jest inna cz, bez potrzeby uywania wielu zagniedo-
nych procedur obsugi zdarze.

Skadniki



Knockout.js

13

Rozwizanie

Knockout.js uywa modeli widoków, które zawieraj logik widoku zwizan
ze zmianami interfejsu. Wasnoci tych modeli mona wiza z elementami
interfejsu.

Chcemy, aby uytkownicy naszej strony mogli zmienia liczb elementów
w koszyku i od razu otrzyma zaktualizowan nalen za nie sum. Do budowy
ekranu aktualizacji naszego koszyka moemy wykorzysta modele widoków Knock-
out. W koszyku kady produkt bdzie przedstawiony w postaci wiersza tabeli.
W kadym wierszu bdzie si znajdowa pole na liczb egzemplarzy danego
produktu oraz przycisk pozwalajcy usun ten produkt z koszyka. Gdy zmieni si
liczba egzemplarzy którego z produktów, aplikacja natychmiast obliczy now
sum czstkow oraz sum za wszystkie towary. Gdy skoczymy prac, finalny
efekt bdzie wyglda jak na rysunku 2.9.

Rysunek 2.9.

Interfejs koszyka

13

http://knockoutjs.com

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

97

Podstawy Knockout

Modele widoków Knockout to zwyke obiekty JavaScript z wasnociami i meto-
dami. Oto prosty obiekt Person z metodami dla imienia, nazwiska oraz imienia
i nazwiska.

knockout/binding.html
var Person = function(){
this.firstname = ko.observable("Jan");
this.lastname = ko.observable("Kowalski");
this.fullname = ko.dependentObservable(function(){
return(
this.firstname() + " " + this.lastname()
);
}, this);
};
ko.applyBindings( new Person );

Metody i logik tego obiektu z elementami interfejsu wiemy przy uyciu atry-
butu

data-

jzyka HTML5.

knockout/binding.html
<p>Imi: <input type="text" data-bind="value: firstname"></p>
<p>Nazwisko: <input type="text" data-bind="value: lastname"></p>
<p>Imi i nazwisko:
<span aria-live="polite" data-bind="text: fullname"></span>
</p>

Gdy zmienimy imi albo nazwisko w jednym z pól, pod spodem zostanie wywie-
tlone zaktualizowane imi i nazwisko. Poniewa aktualizacja odbywa si dyna-
micznie, moe sprawia problemy osobom niewidomym, które korzystaj z czyt-
ników ekranu. Rozwizaniem tego problemu jest uycie atrybutu

aria-live

, infor-

mujcego czytniki, e ta cz strony dynamicznie si zmienia.

To by bardzo prosty przykad, wic teraz pokopiemy troch gbiej i utworzymy
jeden wiersz danych naszego koszyka, w którym po zmianie liczby produktów
bdzie odpowiednio zmieniaa si suma nalena. Póniej na tej bazie zbudujemy
cay koszyk. Zaczniemy od utworzenia modelu danych.

Pojedynczy wiersz bdzie reprezentowa obiekt JavaScript o nazwie

LineItem

majcy wasnoci

name

i

price

. Utwórz stron HTML i docz do niej bibliotek

Knockout.js w sekcji nagówkowej:

knockout/item.html
<!DOCTYPE html>
<html>
<head>
<title>
Aktualizacja liczby produktów</title>
<script type="text/javascript" src="knockout-1.3.0.js"></script>
</head>

Kup książkę

Poleć książkę

background image

98

Web development. Receptury nowej generacji

<body>
</body>

</html>

Na dole strony, nad znacznikiem

</body>

, wstaw element

<script>

i wpisz w nim

nastpujcy kod:

knockout/item.html
var LineItem = function(product_name, product_price){
this.name = product_name;
this.price = product_price;
};

W JavaScripcie funkcje s konstruktorami obiektów, a wic mona ich uywa
do naladowania klas. W tym przypadku konstruktor egzemplarza

LineItem

przyj-

muje nazw i cen.

Teraz musimy poinformowa Knockout, e chcemy uy tej klasy

LineItem

jako

naszego modelu widoku, aby jej wasnoci byy widoczne dla kodu HTML.
W tym celu do skryptu dodajemy poniszy kod.

knockout/item.html
var item = new LineItem("Macbook Pro 15", 1699.00);
ko.applyBindings(item);

Tworzymy nowy egzemplarz obiektu

LineItem

, ustawiajc w nim nazw i cen

produktu, i wywoujemy na nim metod Knockout

applyBindings()

. Póniej

to zmienimy, ale na razie wystarczy nam zakodowanie danych na stae.

Majc obiekt, moemy zbudowa interfejs i pobra z tego obiektu dane. Koszyk
zbudujemy na bazie tabeli HTML z elementami strukturalnymi

<thead>

i

<tbody>

.

knockout/item.html
<div role="application">
<table>
<thead>
<tr>
<th>
Produkt</th>
<th>Cena</th>
<th>Liczba</th>
<th>Suma</th>
</tr>
</thead>
<tbody>
<tr
aria-live="polite">
<td data-bind="text: name"></td>
<td data-bind="text: price"></td>
</tr>
</tbody>
</table>
</div>

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

99

Poniewa wiersze tabeli s aktualizowane danymi wprowadzanymi przez uytkow-
nika, wierszom tym nadalimy atrybut

aria-live

, aby czytniki ekranu wiedziay,

e naley si w nich spodziewa zmian. Cay koszyk dodatkowo umiecilimy
w elemencie

<div>

z atrybutem HTML5-ARIA

application

, który informuje

czytniki, e jest to aplikacja interaktywna. Wicej informacji na temat tych atry-
butów mona przeczyta w specyfikacji HTML5

14

.

Szczególn uwag naley zwróci na ponisze dwa wiersze kodu:

knockout/item.html
<td data-bind="text: name"></td>
<td
data-bind="text: price"></td>

Teraz nasz egzemplarz

LineInstance

jest widoczny globalnie na caej stronie, a wic

tak samo widoczne s jego wasnoci

name

i

price

. Te dwa wiersze kodu ozna-

czaj, e tekst (

text

) tych elementów chcemy pobiera z wasnoci o okrelonych

nazwach.

Gdy teraz wczytamy nasz stron w przegldarce, to zauwaymy, e zaczyna
nabiera ksztatu oraz e pola nazwy i ceny produktu s wypenione!

Teraz dodamy pole, w którym uytkownik bdzie móg zmieni liczb produktów
w zamówieniu.

knockout/item.html
<td><input type="text" name="quantity"
data-bind='value: quantity, valueUpdate: "keyup"'>
</td>

W bibliotece Knockout do odwoywania si do pól danych w postaci elementów
HTML suy parametr

text

, ale elementy formularzy HTML takie jak

<input>

maj atrybut

value

. Dlatego tym razem zwizalimy atrybut

value

z wasnoci

quantity

.

Wasno

quantity

suy nie tylko do wywietlania danych, lecz równie do ich

ustawiania. A gdy ustawimy dane, musimy te uruchomi zdarzenia. Do tego celu
uywamy funkcji Knockout

ko.observable()

jako wartoci wasnoci

quantity

naszej klasy.

this.quantity = ko.observable(1);

Funkcji

ko.observable()

przekazalimy domyln warto, aby po wywietleniu

strony po raz pierwszy pole tekstowe co ju zawierao.

Teraz moemy ju wpisa liczb, ale chcielibymy jeszcze dodatkowo wywietli
sum czstkow dla kadego wiersza. Dodamy do tabeli kolumn na t kwot:

14

http://www.w3.org/TR/html5-author/wai-aria.html

Kup książkę

Poleć książkę

background image

100

Web development. Receptury nowej generacji

knockout/item.html
<td data-bind="text: subtotal "></td>

Podobnie jak w przypadku kolumn nazwy i ceny, tekst komórki ustawiamy na
warto wasnoci

subtotal

modelu widoku.

To doprowadzio nas do jednej z najwaniejszych czci biblioteki Knockout.js,
metody

dependentObservable()

. Wasno

quantity

zdefiniowalimy jako obser-

wowaln, co oznacza, e gdy pole zmieni warto, zmiana ta bdzie zauwaona
przez inne elementy. Deklarujemy metod

dependentObservable()

, która bdzie

wykonywa kod w reakcji na zmian wartoci obserwowanego pola, oraz przypi-
sujemy t metod do wasnoci naszego obiektu, aby mona j byo zwiza
z naszym interfejsem uytkownika.

this.subtotal = ko.dependentObservable(function() {
return(
this.price * parseInt("0"+this.quantity(), 10)
); //<label id="code.subtotal">
}, this);

Ale skd metoda

dependentObservable()

wie, które pola obserwowa? Przeglda

obserwowalne wasnoci, które wymieniamy w definiowanej funkcji. Poniewa
mnoymy cen i liczb, Knockout ledzi obie te wasnoci i wykonuje kod, gdy któ-
rakolwiek z nich si zmieni.

Metoda

dependentObservable()

przyjmuje take drugi parametr, który okrela

kontekst dla wasnoci. Ma to zwizek ze sposobem dziaania funkcji i obiektów
w JavaScripcie. Wicej na ten temat mona przeczyta w dokumentacji biblioteki
Knockout.js.

To wszystko, jeli chodzi o pojedynczy wiersz tabeli. Gdy zmienimy liczb pro-
duktów w zamówieniu, cena zostanie natychmiast zaktualizowana. Teraz roz-
budujemy uzyskan struktur, aby utworzy koszyk na wiele produktów, wywie-
tlajcy dodatkowo sumy czstkowe i ogóln sum nalenoci.

Wizania przepywu sterowania

Wizanie obiektów z elementami HTML jest bardzo wygodne, ale w koszyku
rzadko kiedy jest tylko jeden produkt, a duplikowanie caego tego kodu byoby
bardzo mudne, nie mówic ju o dodatkowych komplikacjach zwizanych z wik-
sz liczb obiektów

LineItem

. Musimy co zmieni.

Zamiast obiektu

LineItem

w roli modelu widoku, do reprezentowania koszyka

uyjemy innego obiektu. Nadamy mu nazw

Cart

i bdziemy w nim przechowy-

wa wszystkie obiekty

LineItem

. Wiedzc, jak dziaa metoda

dependentObservables()

,

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

101

moemy w obiekcie

Cart

utworzy wasno obliczajc sum nalenoci, gdy

zmieni si którykolwiek z elementów koszyka.

A co z kodem HTML dla pojedynczego produktu? Duplikowania kodu moemy
unikn dziki uyciu tzw. wizania przepywu sterowania (ang. control
flow binding
) i nakazujc Knockout wyrenderowanie kodu HTML dla kadego
produktu w koszyku.

Najpierw zdefiniujemy tablic elementów, których uyjemy do napenienia
koszyka.

knockout/update_cart.html
var products = [
{name: "Macbook Pro 15 inch", price: 1699.00},
{name: "Przejciówka Mini Display Port na VGA", price: 29.00},
{name: "Magic Trackpad", price: 69.00},
{name: "Klawiatura bezprzewodowa Apple", price: 69.00}
];

W realnej aplikacji dane te pobieralibymy z usugi sieciowej lub wywoania Ajax
albo generowalibymy je na serwerze podczas serwowania strony.

Teraz utworzymy obiekt

Cart

do przechowywania produktów. Zdefiniujemy go

w taki sam sposób, jak obiekt

LineItem

.

knockout/update_cart.html
var Cart = function(items){
this.items = ko.observableArray();

for(var i in items){
var item = new LineItem(items[i].name, items[i].price);
this.items.push(item);
}
}

Musimy zmieni wizanie z

LineItem

na klas

Cart

.

knockout/update_cart.html
var cartViewModel = new Cart(products);
ko.applyBindings(cartViewModel);

Produkty s zapisywane w koszyku za pomoc metody

observableArray()

, która

dziaa tak samo jak

observable()

, ale ma waciwoci tablicy. Gdy utworzylimy

nowy egzemplarz naszego koszyka, przekazalimy do niego tablic danych. Nasz
obiekt iteruje po elementach danych i tworzy nowe egzemplarze

LineItem

, które

s zapisywane w tablicy produktów. Poniewa tablica ta jest obserwowalna,
interfejs zmieni si po kadej zmianie zawartoci tej tablicy. Oczywicie, teraz
mamy wicej ni jeden produkt, a wic musimy zmodyfikowa nasz interfejs.

Kup książkę

Poleć książkę

background image

102

Web development. Receptury nowej generacji

Ja pyta:

Jak wyglda sprawa dostpnoci
w przypadku biblioteki Knockout?

Interfejsy w duym stopniu oparte na JavaScripcie czsto bardzo sabo
wypadaj pod wzgldem dostpnoci, jednak uycie tego jzyka samo
w sobie o niczym jeszcze nie wiadczy.

W tej recepturze uylimy ról i atrybutów HTML5 ARIA, aby pomóc czyt-
nikom ekranu w zrozumieniu dziaania naszej aplikacji. Jednak kwestie
dostpnoci dotycz nie tylko czytników. W dostpnoci chodzi ogólnie
o umoliwienie dostpu do treci jak najszerszemu gronu odbiorców.

Knockout to rozwizanie napisane w JavaScripcie, a wic dziaa tylko wów-
czas, gdy obsuga tego jzyka jest wczona. Trzeba to bra pod uwag.
Najlepiej jest najpierw napisa aplikacj, która jest uyteczna bez Java-
Scriptu, a nastpnie za pomoc biblioteki Knockout doda róne ulepszenia.
W naszym przykadzie zawarto koszyka jest renderowana za pomoc
biblioteki Knockout, ale gdybymy uyli której z technologii serwerowych,
moglibymy renderowa kod koszyka i stosowa wizania Knockout do
wyrenderowanego kodu HTML. Dostpno aplikacji zaley przede wszyst-
kim od sposobu jej zaimplementowania, a nie od konkretnej uytej do jej
budowy biblioteki.

Nastpnie zmodyfikujemy nasz stron HTML i nakaemy Knockout utworzy
wiersz tabeli dla kadego produktu za pomoc wywoania

data-bind

na elemencie

<tbody>

.

knockout/update_cart.html

h

<tbody data-bind="foreach: items">
<tr aria=live="polite">
<td data-bind="text: name"></td>
<td data-bind="text: price"></td>
<td><input type="text" name="quantity" data-bind='value: quantity'></td>
<td data-bind="text: subtotal "></td>
</tr>
</tbody>

Nakazalimy bibliotece Knockout wyrenderowa zawarto elementu

<tbody>

dla

kadego elementu tablicy

items

. Nie musimy nic wicej zmienia.

Teraz na naszej stronie moe by wywietlanych wiele wierszy tabeli i dla ka-
dego z nich bdzie wywietlana suma czstkowa. Zajmiemy si obliczaniem ca-
kowitej kwoty do zapaty i usuwaniem elementów.

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

103

Kwota do zapaty

Sposób dziaania metody Knockout

dependentObservable()

poznalimy ju przy

okazji obliczania sumy czstkowej dla kadego produktu. Dodajc j do obiektu

Cart

, moemy jej uy take do obliczania sumy cakowitej.

this.total = ko.dependentObservable(function(){
var total = 0;
for (item in this.items()){
total += this.items()[item].subtotal();
}
return total;
}, this);

Kod ten zostanie uruchomiony za kadym razem, gdy zmieni si którykolwiek
z produktów. Aby wywietli sum cakowit, musimy oczywicie jeszcze doda
jeden wiersz do tabeli. Poniewa ma to by suma cakowita nalenoci za wszyst-
kie produkty, wiersz ten umiecimy poza elementem

<tbody>

, w elemencie

<tfoot>

umieszczonym bezporednio pod zamykajcym znacznikiem

</thead>

. Umiesz-

czenie stopki nad treci tabeli pomaga niektórym przegldarkom i technologiom
pomocniczym w szybszym rozpracowaniu struktury tabeli.

knockout/update_cart.html
<tfoot>
<tr>
<td
colspan="4">Naleno</td>
<td aria-live="polite" data-bind="text: total()"></td>
</tr>
</tfoot>

Gdy odwieymy stron i zmienimy liczb przy którym z produktów, nastpi
automatyczna aktualizacja sumy czstkowej i cakowitej. Teraz przejdziemy do
przycisku usuwania produktów.

Usuwanie produktów

Na zakoczenie musimy jeszcze doda przycisk Usu obok kadego produktu,
sucy do jego usunicia z koszyka. Dziki caej wykonanej do tej pory pracy
zadanie to jest ju bardzo atwe. Najpierw dodamy przycisk do tabeli.

<td>
<button
data-bind="click: function() { cartViewModel.remove(this) }">Usu
</button>
</td>

Tym razem zamiast wiza dane z interfejsem, wiemy zdarzenie i funkcj.
Przekazujemy

this

do metody

remove()

wywoywanej na rzecz egzemplarza

cartViewModel

. Przycisk ten jednak nie dziaa, poniewa jeszcze nie zdefiniowa-

limy metody

remove()

. Jej definicja znajduje si poniej:

Kup książkę

Poleć książkę

background image

104

Web development. Receptury nowej generacji

yj w zgodzie z serwerem!

Coraz wiksz popularno zdobywaj koszyki na zakupy, których aktu-
alizacja odbywa si w caoci wycznie po stronie klienta. Czasami po pro-
stu niemoliwe jest wysyanie da Ajax za kadym razem, gdy uytkow-
nik zmieni co w interfejsie.

Stosujc to podejcie, musisz zadba o synchronizacj danych w koszyku
na kliencie z danymi na serwerze. Przecie nie chciaby, aby kto zmienia
ceny produktów za Ciebie!

Gdy uytkownik przechodzi do kasy, naley przesa zaktualizowane war-
toci na serwer i tam obliczy sumy przed sfinalizowaniem transakcji.

knockout/update_cart.html
this.remove = function(item){ this.items.remove(item); }

To wszystko! Poniewa tablica

items

jest obserwowalna (

observableArray

), aktuali-

zowany jest cay interfejs, wraz sum cakowit!

Kontynuacja

Biblioteka Knockout jest doskonaym narzdziem do tworzenia dynamicznych
jednostronicowych interfejsów, a dziki temu, e nie jest zwizana z adnym
frameworkiem sieciowym, moemy jej uywa, gdzie tylko chcemy.

Co waniejsze, modele widoków uywane w tej bibliotece s zwykym kodem
JavaScript, dziki czemu mona jej uywa do implementowania wielu czsto
potrzebnych funkcji interfejsu uytkownika. Na przykad przy uyciu Ajaksa
z atwoci mona by byo utworzy funkcj wyszukiwania biecego, zbudowa
kontrolki do edycji danych przesyajce dane na serwer w celu ich zachowania,
a nawet aktualizowa zawarto jednego menu rozwijanego na podstawie wartoci
wybranej w innym.

Zobacz równie



Receptura 14.: „Organizacja kodu przy uyciu biblioteki Backbone.js”

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

105

Receptura 14.
Organizacja kodu
przy uyciu biblioteki Backbone.js

Problem

W odpowiedzi na rosnce wymagania uytkowników w kwestii niezawodnoci
i interaktywnoci aplikacji dziaajcych po stronie klienta, programici cigle
tworz nowe niesamowite biblioteki JavaScript. Jednak im bardziej skompliko-
wana jest dana aplikacja, tym bardziej jej kod wyglda jak pobojowisko pene
porozrzucanych bez adu i skadu rozmaitych bibliotek, wiza zdarze, wywo-
a Ajax jQuery i funkcji przetwarzajcych dane w formacie JSON.

Potrzebna jest nam metoda tworzenia aplikacji dziaajcych po stronie klienta
w taki sam sposób, jak od lat tworzymy aplikacje serwerowe. Krótko mówic,
potrzebujemy jakiego frameworku. Majc solidny framework JavaScript, utrzy-
mamy porzdek w programie, zredukujemy powtarzalno kodu oraz zastosujemy
standard zrozumiay take dla innych programistów.

Poniewa Backbone to skomplikowana biblioteka, ta receptura jest
znacznie dusza i bardziej skomplikowana od innych.

Skadniki



Backbone.js

15



Underscore.js

16



JSON2.js

17



Mustache

18



jQuery



QEDServer

15

http://documentcloud.github.com/backbone

16

http://documentcloud.github.com/underscore/

17

https://github.com/douglascrockford/JSON-js

18

http://mustache.github.com/

Kup książkę

Poleć książkę

background image

106

Web development. Receptury nowej generacji

Rozwizanie

To zadanie moemy wykona przy uyciu wielu rónych frameworków, ale
Backbone.js jest jednym z najpopularniejszych, dziki swojej elastycznoci,
niezawodnoci i ogólnie wysokiej jakoci kodu. W chwili pisania tych sów by
jeszcze wzgldnie nowy, a mia ju wielu uytkowników. Przy uyciu Backbone
moemy wiza zdarzenia w podobny sposób, jak to robilimy przy uyciu
Knockout w recepturze 13., „Tworzenie interaktywnych interfejsów uytkownika
przy uyciu biblioteki Knockout.js”, ale teraz otrzymujemy modele wspópracujce
z serwerem oraz system trasowania da, za pomoc którego mona ledzi zmiany
w adresach URL. Dziki Backbone otrzymujemy bardziej niezawodny zrb apli-
kacji, który moe doskonale sprawdzi si w przypadku skomplikowanych aplikacji
serwerowych, ale stanowi przerost formy nad treci w przypadku prostszych
programów.

Uyjemy Backbone do poprawienia wraliwoci interfejsu naszego sklepu inter-
netowego, tzn. sprawimy, e bdzie ywiej reagowa na dziaania uytkownika.
Z naszych logów i bada zachowa uytkowników wynika, e odwieanie strony
trwa zbyt dugo, a wiele rzeczy, które wykonuje si za porednictwem serwera,
mona by byo zrobi na kliencie. Nasz kierownik zasugerowa, abymy cay
interfejs zarzdzania produktami zmiecili na pojedynczej stronie, na której bdzie
mona dodawa i usuwa produkty bez odwieania strony.

Zanim rozpoczniemy budow naszego interfejsu, bliej poznamy Backbone
i dowiemy si, jak za pomoc tej biblioteki moemy rozwiza nasz problem.

Podstawy Backbone

Backbone to dziaajca po stronie klienta implementacja wzorca model-widok-
-kontroler, na powstanie której duy wpyw miay serwerowe frameworki, takie
jak ASP.NET MVC i Ruby on Rails. Backbone ma kilka komponentów poma-
gajcych dobrze zorganizowa kod zwizany z komunikacj z serwerem.

Modele reprezentuj dane i mog wspópracowa z naszym zapleczem za pored-
nictwem Ajaksa. Ponadto s doskonaym miejscem na wpisanie logiki biznesowej
i kodu sprawdzajcego poprawno danych.

Widoki w Backbone nieco róni si od widoków w innych frameworkach. S nie
tyle warstw prezentacji, co raczej „kontrolerami widoku”. W interfejsie typowej
aplikacji dziaajcej po stronie klienta moe by wiele zdarze. Kod wywoywany
przez te zdarzenia jest przechowywany wanie w tych widokach. Nastpnie mog
one renderowa szablony i modyfikowa nasz interfejs uytkownika.

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

107

Routery ledz zmiany adresu URL i mog wiza ze sob modele i widoki.
Gdy chcemy pokaza w interfejsie róne „strony” lub karty, do obsugi da
i w celu wywietlania rónych widoków moemy uy routerów. W Backbone
obsuguj one take przycisk Wstecz przegldarki.

W kocu w Backbone dostpne s kolekcje, dziki którym moemy atwo pobie-
ra zbiory egzemplarzy modeli, z którymi chcemy pracowa. Na rysunku 2.10
pokazano, jak poszczególne elementy Backbone ze sob wspópracuj oraz w jaki
sposób uyjemy ich do budowy naszego interfejsu do zarzdzania produktami.

Rysunek 2.10.

Skadniki Backbone

Domylnie modele Backbone komunikuj si z serwerow aplikacj RESTful
przy uyciu metody

ajax()

z biblioteki jQuery i formatu JSON. Zaplecze musi

akceptowa dania

GET

,

POST

,

PUT

i

DELETE

oraz rozpoznawa dane w formacie

JSON w treci tych da. S to jednak tylko ustawienia domylne, które mona
zmodyfikowa. W dokumentacji Backbone znajduj si informacje na temat tego,
jak zmodyfikowa kod dziaajcy po stronie klienta tak, aby wspópracowa
z rónymi rodzajami zapleczy.

Nasze zaplecze bdzie obsugiwa domylne ustawienia, a wic bdziemy mogli
wywoywa niektóre metody na modelach Backbone, a framework bdzie niepo-
strzeenie serializowa i deserializowa informacje o naszych produktach.

Kup książkę

Poleć książkę

background image

108

Web development. Receptury nowej generacji

I jeszcze jedna uwaga na koniec: jak napisalimy w ramce „Jak wyglda sprawa
dostpnoci w przypadku biblioteki Knockout?”, frameworków typu Backbone
najlepiej jest uywa jako nakadek na ju istniejce strony internetowe, aby
ulepszy ich cechy uytkowe. Jeli Twój kod dziaajcy po stronie klienta bdzie
zbudowany na solidnej podstawie, atwiej bdzie opracowa rozwizanie dziaa-
jce take bez JavaScriptu. W tej recepturze pracujemy z interfejsem, który ju ma
wersj dziaajc bez JavaScriptu.

Budowa interfejsu

Zbudujemy prosty, mieszczcy si na jednej stronie interfejs do zarzdzania
produktami w naszym sklepie. Jego schemat przedstawiony jest na rysunku 2.11.
Na górze strony bdzie si znajdowa formularz do dodawania produktów, a pod
nim umiecimy list produktów. Dane z magazynu produktów bdziemy pobiera
i modyfikowa przy uyciu Backbone i jego interfejsu w stylu REST:



danie

GET()

do http://przyklad.com/products.json pobiera list pro-

duktów.



danie

GET

do /products/1.json pobiera dane produktu o identyfikatorze

1

w formacie JSON.



danie

POST

do /products.json z reprezentacj produktu w formacie

JSON w treci tworzy nowy produkt.



danie

PUT

do http://example.com/products/1.json z reprezentacj pro-

duktu w formacie JSON w treci aktualizuje produkt o identyfikatorze

1

.



danie

DELETE

do /products/1.json usuwa produkt o identyfikatorze

1

.

Poniewa dania Ajax musz by wykonywane do tej samej domeny, do testo-
wania uyjemy serwera QEDServer i jego API do zarzdzania produktami.
Wszystkie nasze pliki umiecimy w folderze public utworzonym przez serwer
w przestrzeni roboczej.

Budow interfejsu rozpoczniemy od utworzenia modelu produktu i kolekcji do
przechowywania wielu modeli produktów. dania wywietlenia listy produktów
i formularza dodawania nowego produktu obsuymy za pomoc routera. Ponadto
utworzymy widoki listy produktów i formularza produktu.

Najpierw utworzymy folder lib na bibliotek Backbone i jej zalenoci.

$ mkdir javascripts
$ mkdir javascripts/lib

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

109

Rysunek 2.11.

Nasz interfejs do zarzdzania produktami

Nastpnie pobierzemy Backbone.js wraz ze wszystkimi skadnikami ze strony in-
ternetowej

19

. W tej recepturze uywamy Backbone 0.5.3. Biblioteka ta wymaga

obecnoci biblioteki Underscore.js zawierajcej pewne funkcje wykorzystywane
wewntrznie przez Backbone, a dziki którym my moemy zaoszczdzi na
pisaniu kodu. Dodatkowo potrzebujemy biblioteki JSON2, która ma rozszerzone
moliwoci w zakresie obróbki danych w formacie JSON w przegldarkach.
Dodatkowo przyda nam si jzyk szablonowy biblioteki Mustache

20

. Pobierz

wszystkie te pliki i umie je w folderze javascripts/lib.

Na koniec utworzymy plik o nazwie app.js w folderze javascripts. W pliku tym
bd si znajdowa wszystkie nasze skadniki Backbone i nasz wasny kod.

19

http://documentcloud.github.com/backbone/

20

Aby nie traci czasu, wszystkie potrzebne pliki znajdziesz w kodzie ródowym doczo-
nym do tej ksiki.

Kup książkę

Poleć książkę

background image

110

Web development. Receptury nowej generacji

Mimo i mona by byo utworzy z tego dwa pliki, to jednak w ten sposób przy
kadym wczytywaniu strony oszczdzamy jedno odwoanie do serwera.

Majc przygotowane wszystkie pliki, utworzymy bardzo prosty szkielet HTML
w pliku index.html, w którym bd znajdoway si skadniki naszego interfejsu
uytkownika oraz bd doczone pozostae pliki. Zaczniemy od zdefiniowania
typowych elementów strukturalnych oraz utworzymy elementy

<div>

na wiadomoci

dla uytkownika, formularz i list produktów (

<ul>

).

backbone/public/index.html
<!DOCTYPE html>
<html>
<head>
<title>Zarzdzanie produktami </title>
</head>
<body role="application">
<h1>Produkty</h1>
<div aria-live="polite" id="notice">
</div>
<div aria-live="polite" id="form">
</div>
<p><a href="#new">Nowy produkt</a></p>

<ul aria-live="polite" id="list">
</ul>
</body>
</html>

Te obszary bd aktualizowane bez odwieania strony, w zwizku z czym
dodalimy atrybuty ARIA HTML5, aby poinformowa czytniki ekranu, jak
maj obsugiwa te zdarzenia

21

.

Pod tymi obszarami, a bezporednio nad zamykajcym znacznikiem

</body>

umie-

cimy jQuery i Backbone z zalenociami oraz plik app.js:

Backbone/public/index.html
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js">
</script>
<script
type="text/javascript"
src="javascripts/lib/json2.js"></script>
<script
type="text/javascript"
src="javascripts/lib/underscore-min.js"></script>
<script
type="text/javascript"
src="javascripts/lib/backbone-min.js"></script>
<script
type="text/javascript"
src="javascripts/lib/mustache.js"></script>
<script
type="text/javascript"
src="javascripts/app.js"></script>

21

http://www.w3.org/TR/html5-author/wai-aria.html

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

111

Teraz moemy rozpocz tworzenie listy produktów.

Tworzenie listy produktów

Aby utworzy list produktów, pobierzemy produkty z naszego zaplecza Ajax.
Do tego celu potrzebne nam bd model i kolekcja. Model bdzie reprezentowa
pojedynczy produkt, a kolekcja — grup produktów. Tworzc i usuwajc pro-
dukty, bdziemy korzysta bezporednio z modelu. Natomiast pobierajc list
produktów z serwera, moemy uy kolekcji w celu pobrania rekordów i otrzyma-
nia grupy modeli Backbone, z którymi bdziemy mogli pracowa.

Najpierw utworzymy model. W pliku javascripts/app.js umiecimy nastpujc
definicj obiektu

Product

:

backbone/public/javascripts/app.js
var Product = Backbone.Model.extend({

defaults: {
name: "",
description: "",
price: ""
},
url : function() {
return(this.isNew() ? "/products.json" : "/products/" + this.id + ".json");
}
});

Ustawilimy kilka domylnych wartoci dla przypadków, w których nie bdzie
adnych danych, jak np. gdy tworzymy nowy egzemplarz. Nastpnie informujemy
model, skd ma pobiera swoje dane. Backbone uywa do tego celu metody

url()

modelu, któr musimy wypeni.

Majc zdefiniowany model, moemy utworzy kolekcj, której uyjemy do pobra-
nia wszystkich produktów dla naszej strony listy.

backbone/public/javascripts/app.js
var ProductsCollection = Backbone.Collection.extend({
model: Product,
url: '/products.json'
});

Kolekcja, podobnie jak model, ma metod

url()

, któr musimy zaimplementowa.

Poniewa jednak chcemy tylko pobra list wszystkich produktów, moemy po
prostu na sztywno wpisa adres URL /products.json.

Poniewa z kolekcji tej bdziemy korzysta w kilku miejscach naszej aplikacji,
utworzymy jej egzemplarz. Obiekt ten zostanie utworzony na samym pocztku
pliku javascripts/app.js.

Kup książkę

Poleć książkę

background image

112

Web development. Receptury nowej generacji

backbone/public/javascripts/app.js
$(function(){
window.products = new ProductsCollection();

Obiekt kolekcji wiemy z obiektem

window

, dziki czemu póniej bdziemy mieli

do niego atwy dostp z rónych widoków.

Mamy zdefiniowane model i kolekcj, a wic moemy przej do widoku.

Szablon listy i widok

Widoki w Backbone zawieraj logik odpowiedzialn za zmienianie interfejsu
w reakcji na zdarzenia. Do renderowania naszej listy produktów uyjemy dwóch
widoków. Jeden z nich bdzie reprezentowa pojedynczy produkt przy uyciu
szablonu Mustache i obsugiwa wszystkie zdarzenia zwizane z tym produktem.
Natomiast drugi widok bdzie iterowa przez kolekcj produktów i renderowa
pierwszy widok dla kadego obiektu, umieszczajc wyniki na naszej stronie. Dziki
temu bdziemy mieli szczegóow kontrol nad kadym skadnikiem.

Najpierw utworzymy prosty szablon Mustache, którego nasze widoki Backbone
bd uywa do iterowania przez kolekcj produktów. Szablon ten dodamy do
strony index.html, nad elementami

<script>

doczajcymi biblioteki:

backbone/public/index.html
<script type="text/html" id="product_template">
<li>
<h3>
{{name}} - {{price}}
<button class="delete">Usu</button>
</h3>
<p>{{description}}</p>
</li>
</script>

Wywietlamy nazw produktu, cen i opis oraz przycisk do usuwania tego pro-
duktu.

Nastpnie utworzymy nowy widok, o nazwie

ProductView

, rozszerzajc klas

Backbone

View

i definiujc kilka kluczowych elementów.

backbone/public/javascripts/app.js
ProductView = Backbone.View.extend({
template: $("#product_template"),
initialize: function(){
this.render();
},
render: function(){
}
});

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

113

Najpierw za pomoc jQuery pobralimy ze strony indeksowej nasz szablon
Mustache, posugujc si jego identyfikatorem, i zapisalimy go we wasnoci
o nazwie

template

. Dziki temu nie bdziemy musieli pobiera tego szablonu

ze strony za kadym razem, gdy chcemy wyrenderowa jaki produkt.

Nastpnie definiujemy funkcj

initialize()

, która bdzie uruchamiana po utwo-

rzeniu nowego egzemplarza

ListView

i która bdzie wywoywaa funkcj

render()

widoku.

Kady widok ma domyln funkcj

render()

, któr trzeba przedefiniowa, aby

robia to, co chcemy. W naszym przypadku bdzie ona renderowaa szablon
Mustache pobierany ze zmiennej

template

. Poniewa w zmiennej tej przechowy-

wany jest obiekt jQuery, musimy wywoa metod

html()

, aby pobra zawarto

szablonu z tego obiektu.

backbone/public/javascripts/app.js
render: function(){
var html = Mustache.to_html(this.template.html(), this.model.toJSON() );
$(this.el).html(html);
return this;
}

W metodzie tej uylimy odwoania do modelu

this.model

, który bdzie zawiera

potrzebn nam list produktów. Gdy utworzymy nowy egzemplarz widoku,
moemy do niego przypisa model lub kolekcj, aby móc si do nich odwoywa
w metodach widoku bez koniecznoci ich przekazywania, podobnie jak zrobilimy
z szablonem Mustache. Wywoujemy funkcj

toJSON()

na naszym modelu, który

przekazujemy do szablonu, aby dane tego modelu byy atwo dostpne w szablonie.

Metoda

render()

zapisuje kod HTML wyrenderowany z szablonu Mustache

we wasnoci widoku o nazwie

el

i zwraca ten egzemplarz widoku

ProductView

.

Gdy wywoamy t metod, pobierzemy wyniki z tej wasnoci i dodamy je do
strony.

W tym celu utworzymy widok o nazwie

ListView

i strukturze bardzo podobnej

do struktury widoku

ProductView

, tylko zamiast renderowa szablon Mustache,

bdzie on iterowa po kolekcji produktów i dla kadego z nich renderowa widok

ProductView

.

backbone/public/javascripts/app.js
ListView = Backbone.View.extend({
el: $("#list"),

initialize: function() {
this.render();
},

renderProduct: function(product){

Kup książkę

Poleć książkę

background image

114

Web development. Receptury nowej generacji

var productView = new ProductView({model: product});
this.el.append(productView.render().el);
},

render: function() {
if(this.collection.length > 0) {
this.collection.each(this.renderProduct, this);
} else {
$("#notice").html("Brak produktów do wywietlenia.");
}
}
});

Musimy aktualizowa zawarto obszaru

list

na naszej stronie z list produktów.

Odwoanie do tego obszaru przechowujemy we wasnoci o nazwie

el

. Dziki

temu mamy wygodny dostp do tej listy w metodzie

render()

. W podobny sposób

postpilimy z szablonem Mustache w widoku

ProductView

.

Backbone korzysta z biblioteki Underscore.js, zawierajcej funkcje uatwiajce
prac z kolekcjami. W metodzie

render()

iterujemy przez kolekcj przy uyciu

metody

each()

i wywoujemy nasz metod

renderProduct

. Metoda

each()

automa-

tycznie przekazuje produkt. Jako drugi parametr przekazujemy

this

, co oznacza,

e kontekstem dla metody

renderProduct()

ma by widok. Bez tego metoda

each()

szukaaby metody

renderProduct()

w kolekcji, co uniemoliwioby jej dziaanie.

Zdefiniowalimy model, kolekcj i dwa widoki oraz dodalimy szablon, ale wci
nie mamy dla niego nic do wywietlenia. Musimy to wszystko poczy ze sob
podczas adowania strony w przegldarce. Do tego celu uyjemy routera.

Obsuga zmian adresów URL przy uyciu routerów

Podczas wczytywania strony bdzie uruchamiany kod pobierajcy kolekcj pro-
duktów z API Ajax. Nastpnie kolekcja ta bdzie przekazywana do nowego
egzemplarza widoku

ListView

w celu wywietlenia produktów. Routery Backbone

umoliwiaj wywoywanie funkcji w reakcji na zmiany adresu URL.

Utworzymy router o nazwie

ProductsRouter

. W tym celu rozszerzymy router

Backbone i zdefiniujemy tras mapujc cz adresu URL znajdujc si za
znakiem # na funkcj w naszym routerze. Dla domylnego przypadku odpowia-
dajcego sytuacji, gdy w adresie URL nie ma znaku #, zdefiniujemy pust tras,
któr zwiemy z funkcj o nazwie

index()

. Ta domylna trasa bdzie urucho-

miona przy wczytywaniu strony index.html.

backbone/public/javascripts/app.js
ProductsRouter = Backbone.Router.extend({
routes: {
"": "index"
},

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

115

index: function() {
}
});

W akcji

index()

wywoujemy metod

fetch()

naszej kolekcji produktów, aby

pobra dane z serwera.

backbone/public/javascripts/app.js
index: function() {
window.products.fetch({
success: function(){
new ListView({ collection: window.products });
},
error: function(){
$("#notice").html("Nie mona zaadowa produktów.");
}
});
}

Metoda

fetch()

pobiera funkcje zwrotne

success

i

error

. Gdy wystpi jaki bd,

wywietlamy komunikat o bdzie w obszarze

notice

strony. Gdy natomiast otrzy-

mamy kolekcj danych, zostaje wywoana funkcja zwrotna

success()

i nastpuje

utworzenie egzemplarza widoku. Poniewa dziki naszej metodzie widoku

initialize()

widok listy jest renderowany automatycznie, pozostaje nam jedynie

utworzenie nowego egzemplarza routera, aby to wszystko uruchomi.

W pliku javascripts/app.js pod definicj

window.productsCollection

tworzymy

egzemplarz routera. Nastpnie nakazujemy Backbone ledzenie zmian w adre-
sie URL.

backbone/public/javascripts/app.js
window.products = new ProductsCollection();
$.ajaxSetup({ cache: false });
window.router = new ProductsRouter();
Backbone.history.start();

Do rozpoczcia ledzenia zmian w adresie URL Backbone zmusza wiersz kodu

Backbone.history.start();

. Jeli zapomnimy o nim, router nie bdzie dziaa i na

stronie nic si nie bdzie dziao.

Poniszy wiersz wycza zapisywanie przez niektóre przegldarki w pamici
podrcznej odpowiedzi Ajax z serwera:

$.ajaxSetup({ cache: false });

Gdy teraz wejdziemy na stron http://localhost:8080/index.html, w kocu zoba-
czymy list naszych produktów.

Podsumujmy, co do tej pory zrobilimy. Mamy router obserwujcy adres URL
i wywoujcy metod, która przy uyciu naszej kolekcji pobiera modele z naszej
usugi sieciowej. Kolekcja ta jest nastpnie przekazywana do widoku, który

Kup książkę

Poleć książkę

background image

116

Web development. Receptury nowej generacji

renderuje szablon i wysya go do interfejsu uytkownika. Interakcje te s przedsta-
wione w postaci schematu na rysunku 2.12. Moe si wydawa, e to wszystko
jest zbyt skomplikowane, jak na tak proste zadanie. Jednak w miar ewolucji
kodu pozwoli to zaoszczdzi ogromne iloci czasu. Stworzylimy podstawow
infrastruktur do dodawania, aktualizowania i usuwania produktów i nie bdziemy
musieli ju si tym wicej przejmowa. Teraz dodamy moliwo dodawania
produktów.

Rysunek 2.12.

Wywietlanie listy produktów przy uyciu Backbone

Tworzenie nowego produktu

Mechanizm tworzenia nowych produktów bdzie dziaa w ten sposób, e gdy
uytkownik kliknie cze Nowy produkt, na stronie pojawi si specjalny formularz.
Gdy uytkownik wypeni ten formularz, pobierzemy z niego dane, przekaemy je
do naszego zaplecza, a nastpnie wywietlimy na licie.

Zaczniemy od dodania szablonu Mustache dla formularza na stronie index.html.
Wstawimy go pod szablonem produktu, ale nad elementami

<script>

doczaj-

cymi nasze biblioteki:

backbone/public/index.html
<script type="text/html" id="product_form_template">
<form>
<div
class="row">
<label>
Nazwa<br>
<input id="product_name" type="text" name="name"
value="{{name}}">
</label>

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

117

</div>
<div
class="row">
<label>Opis<br>
<textarea id="product_description"
name="description">{{description}}</textarea>
</label>
</div>
<div
class="row">
<label>Cena<br>
<input id="product_price" type="text" name="price"
value="{{price}}">
</label>
</div>
<button>
Zapisz</button>
</form>
<p><a
id="cancel" href="#">Anuluj</a></p>
</script>

Znaczniki szablonu Mustache bd pobiera wartoci z modelu i wstawia je do
pól formularza. Dlatego wanie ustawilimy domylne wartoci w modelu Back-
bone. Szablonu tego moglibymy take uy ponownie do edycji rekordów.

Teraz potrzebujemy widoku do renderowania tego szablonu z modelu. W pliku
javascripts/app.js utworzymy nowy widok o nazwie

FormView

, podobny do tego,

który utworzylimy dla naszej listy. Tym razem jednak zmienn

el

ustawimy na

obszar

form

strony, a funkcja

render()

bdzie pobiera szablon formularza i ren-

derowa wynik w tym obszarze.

backbone/public/javascripts/app.js
FormView = Backbone.View.extend({
el: $("#form"),
template: $("#product_form_template"),
initialize: function(){
this.render();
},
render: function(){
var html = Mustache.to_html(this.template.html(), this.model.toJSON() );
this.el.html(html);
}
});

Gdy uytkownik kliknie cze Nowy produkt, widok powinien renderowa na
stronie formularz. Poniewa w wyniku tego nastpuje zmiana w adresie URL
polegajca na dodaniu do niego czci

#new

, moemy zdarzenie to obsuy za

pomoc routera. Najpierw musimy w sekcji tras doda tras

#new

, która odpowiada

miejscu wskazywanemu przez cze Nowy produkt.

backbone/public/javascripts/app.js
routes: {
"new": "newProduct",
"": "index"
},

Kup książkę

Poleć książkę

background image

118

Web development. Receptury nowej generacji

Nastpnie musimy zdefiniowa funkcj pobierajc nowy model i przekazujc go
do nowego egzemplarza widoku formularza, aby widok ten móg zosta wyren-
derowany na stronie. Metod t umiecimy nad metod

index()

, a poniewa

deklaracje tych metod s zdefiniowane jako wasnoci obiektu

this

, musimy je

rozdzieli przecinkiem.

backbone/public/javascripts/app.js
newProduct: function() {
new FormView( {model: new Product()});
},

Gdy odwieymy stron i klikniemy cze Nowy produkt, zostanie wywietlony nasz
formularz. Dziki mechanizmowi ledzenia historii Backbone, gdy naciniemy
przycisk Wstecz przegldarki, adres URL ulegnie zmianie. Nie moemy jednak
jeszcze zapisywa nowych rekordów. Zajmiemy si tym teraz.

Reagowanie na zdarzenia w widoku

Uylimy naszego routera do wywietlenia formularza, ale routery reaguj tylko na
zmiany adresu URL. A musimy jeszcze doda obsug zdarze kliknicia przyci-
sków Zapisz i Anuluj. Zrobimy to w utworzonym wczeniej widoku formularza.

Zaczniemy od zdefiniowania zdarze dla widoku do obserwacji. Dodamy je do
widoku przed funkcj

initialize()

:

backbone/public/javascripts/app.js
events: {
"click .delete": "destroy"
},
events: {
"click #cancel": "close",
"submit form": "save",
},

Uyta tu skadnia nieco róni si od typowej skadni monitorowania zdarze
JavaScriptu. Klucz tablicy definiuje obserwowane zdarzenie. Po nim znajduje si
selektor CSS elementu, który ma by obserwowany. Natomiast warto okrela
funkcj widoku, któr chcemy wywoywa. W tym przypadku obserwujemy zda-
rzenie kliknicia dla przycisku anulowania i zdarzenie zatwierdzenia caego for-
mularza.

Kod obsugujcy cze „zamykania” jest prosty — po prostu usuwamy tre ele-
mentu HTML zawierajcego ten widok:

backbone/public/javascripts/app.js
close: function(){
this.el.unbind();
this.el.empty();
},

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

119

Metoda

save()

jest nieco bardziej skomplikowana. Najpierw wyczamy zatwier-

dzanie formularza, a nastpnie pobieramy wartoci wszystkich pól i umieszczamy
je w nowej tablicy. Póniej ustawiamy atrybuty modelu i wywoujemy jego metod

save()

.

backbone/public/javascripts/app.js
save: function(e){
e.preventDefault();
data = {
name: $("#product_name").val(),
description: $("#product_description").val(),
price: $("#product_price").val()
};
var self = this;
this.model.save(data, {
success: function(model, resp) {
$("#notice").html("Produkt zosta zapisany.");
window.products.add(self.model);
window.router.navigate("#");
self.close();
},
error: function(model, resp){
$("#notice").html("Bdy uniemoliwiy utworzenie produktu.");
}
});
},

Sposób uycia metody

save()

jest podobny do sposobu uycia metody

fetch()

,

tzn. naley zdefiniowa zarówno zachowanie w przypadku powodzenia, jak i nie-
powodzenia. Poniewa funkcje tych zachowa dziaaj w rónych kontekstach,
tworzymy tymczasow zmienn o nazwie

self

, do której przypisujemy biecy

kontekst, aby móc si do niego odwoa w metodzie powodzenia. W odrónieniu
od metody

each()

, której uywalimy do renderowania listy produktów, Backbone

nie umoliwia przekazywania parametru kontekstu do funkcji zwrotnych

22

.

Gdy zapisywanie danych powiedzie si, dodajemy nowy model do kolekcji i za
pomoc routera zmieniamy adres URL. Nie powoduje to jednak uruchomienia
odpowiedniej funkcji w routerze, przez co nie zobaczymy naszego produktu na
licie. Mona to jednak atwo naprawi dziki wizaniom zdarze w Backbone.

Gdy dodajemy model do kolekcji, kolekcja ta wywouje zdarzenie

add

, które

moemy obserwowa. Pamitasz metod

renderProduct()

z widoku listy? Moemy

sprawi, aby metoda ta bya wywoywana za kadym razem, gdy dodajemy model
do naszej kolekcji. Wystarczy w tym celu doda poniszy wiersz kodu do metody

initialize()

widoku

ListView

:

22

Przynajmniej w czasie pisania tej ksiki.

Kup książkę

Poleć książkę

background image

120

Web development. Receptury nowej generacji

backbone/public/javascripts/app.js
this.collection.bind("add", this.renderProduct, this);

Metoda

bind()

umoliwia dokonywanie wiza ze zdarzeniami i jako argumenty

przyjmuje nazw zdarzenia, funkcj oraz kontekst. Jako trzeci argument przeka-
zalimy

this

, co oznacza, e chcemy, aby kontekstem by widok, a nie kolekcja.

Podobnie zrobilimy w metodzie

render()

widoku listy z

collection.each

.

Poniewa do dodania rekordu uylimy istniejcej metody

renderProduct()

, nowy

rekord zosta dodany na dole listy. Aby rekordy byy dodawane na pocztku listy,
moemy napisa now metod

addProduct()

, która uywaaby metody

prepend()

jQuery. Pozostawiamy to jednak jako zadanie do samodzielnego wykonania.

Moemy ju tworzy nowe produkty i wywietla ich list na stronie bez odwie-
ania. Czas doda mechanizm usuwania produktów. Teraz wanie skorzystamy
z dobrej organizacji naszego kodu.

Usuwanie produktu

Aby usun produkt, wykorzystamy umiejtnoci zdobyte podczas pracy nad wido-
kiem

FormView

oraz zaimplementujemy funkcj

destroy()

w widoku

ProductView

,

która bdzie wywoywana w wyniku nacinicia przycisku Usu.

Najpierw zdefiniujemy zdarzenie do obserwacji klikni przycisków nalecych
do klasy

delete

.

backbone/public/javascripts/app.js
events: {
"click .delete": "destroy"
},
events: {
"click #cancel": "close",
"submit form": "save",
},

Nastpnie definiujemy metod

destroy()

, któr to zdarzenie bdzie wywoywa.

W metodzie tej wywoamy metod

destroy()

modelu zwizanego z tym widokiem.

Zastosowanie ma w niej ta sama strategia powodzenia i bdu, której uywalimy
wczeniej. Skorzystamy te ze sztuczki ze sowem kluczowym

self

, aby obej

problemy z kontekstem, podobnie jak to zrobilimy przy zapisywaniu rekordów
w widoku formularza.

backbone/public/javascripts/app.js
destroy: function(){
var self = this;
this.model.destroy({
success: function(){
self.remove();
},

Kup książkę

Poleć książkę

background image

Rozdzia 2. • Interfejs uytkownika

121

error: function(){
$("#notice").html("Wystpi problem podczas usuwania produktu.");
}
});
},

Gdy model zostanie usunity przez serwer, nastpuje wywoanie metody zwrotnej

success

wywoujcej metod

remove()

widoku, co powoduje zniknicie rekordu

z listy. Jeli co pójdzie nie tak, wywietlamy odpowiedni wiadomo.

To wszystko! Mamy prosty, dobrze zorganizowany prototyp, którym moemy si
ju chwali albo który moemy dalej rozwija.

Kontynuacja

Opisana aplikacja jest dobra na pocztek, ale jest par rzeczy, które mona
poprawi.

Po pierwsze, za pomoc jQuery aktualizujemy uwag

notice

w kilku miejscach:

$("#notice").html("Produkt zosta zapisany.");

Mona by byo utworzy funkcj opakowujc do oddzielenia tego od kodu
HTML albo nawet uy innego widoku Backbone i szablonu Mustache, aby
wywietli te wiadomoci.

Gdy zapisujemy rekordy, wartoci z formularza pobieramy przy uyciu selektorów
jQuery. Dane mona by byo umieszcza od razu w egzemplarzu modelu przy
uyciu zdarze

onchange

pól formularza.

W tej recepturze przedstawilimy rozwizania dotyczce dodawania i usuwania
rekordów, ale mona jeszcze doda moliwo ich edycji. Moemy uy routera
do wywietlania formularza, a nawet wykorzysta ten sam widok formularza, któ-
rego uywalimy do tworzenia produktów.

Backbone to doskonay system usprawniajcy prac z danymi zapleczowymi, ale
to dopiero pocztek. Nie musisz uywa Ajaksa. Równie dobrze dane moesz
zapisywa na kliencie przy uyciu HTML5.

W celu lepszej integracji z aplikacjami serwerowymi Backbone obsuguje metod

pushState()

obiektu

History

HTML5, dziki czemu mona uywa prawdziwych

adresów URL zamiast fragmentów ze znakiem #. Dodatkowo mona opracowa
mechanizmy awaryjne, które bd serwowa strony, gdy wyczona jest obsuga
JavaScriptu.

Kup książkę

Poleć książkę

background image

122

Web development. Receptury nowej generacji

Dziki wielu opcjom i doskonaej obsudze Ajaksa Backbone jest niezwykle ela-
stycznym frameworkiem, który najlepiej sprawdza si w sytuacjach, gdy potrzebna
jest dobrze zorganizowana struktura kodu.

Zobacz równie



Receptura 10.: „Tworzenie szablonów HTML przy uyciu systemu
Mustache”



Receptura 13.: „Tworzenie interaktywnych interfejsów uytkownika przy
uyciu biblioteki Knockout.js”

Kup książkę

Poleć książkę

background image

Skorowidz

A

adres URL, 94
akcja index(), 115
aktualizowanie adresu

URL, 94

animacja poysku, 31
animacje, 28
API Flickr, 144
API History, 95
API JavaScript Map

Google, 125

API Map Google, 123
API QEDServer, 86
API Sauce Labs, 250
aplikacja

RESTful, 107
CouchApp, 156

archiwum ClickHeat, 240
arkusze stylów, 54
asercje, 243
atrapa, mock, 267
atrybut

action, 138
aria-live, 99
data, 97
data-direction, 185
data-icon, 180
data-product-id, 183

data-role, 180
media, 165
value, 142

atrybuty HTML5 ARIA,

102, 110

automatyczne

dopasowanie treci, 165
przewijanie, 35

automatyzacja

procesów, 302
wdraania, 301

B

baza danych CouchDB,

153, 155, 161

bazy danych, 154
BDD, behavior-driven

development, 248

biblioteka

Backbone.js, 95, 105
HAML, 198
Highcharts, 130, 136
HTMLShiv, 194
Jekyll, 200
jQuery, 13
jQuery 1.6.4, 179
jQuery Mobile, 178
jQuery UI Effects, 45

Knockout, 96, 104
Mustache, 109

blog, 200
blok describe(), 262
blokowanie adresów IP, 291
bdy, 143

w formularzu, 140
w kodzie, 234

budowa serwisu, 203

C

cechy Cucumber, 253
certyfikaty SNI, 288
cienie, 197
CSS3, 22
CTH, Cucumber Testing

Harness, 249

cudzysów, 24
cytat blokowy, 24
czas transformacji, 32
czytniki ekranu, 99

D

debugowanie, 236
debugowanie JavaScriptu,

233, 265

definicja przejcia, 31

Kup książkę

Poleć książkę

background image

312

Web development. Receptury nowej generacji

definiowanie wasnych

atrybutów, 41

deklaracja

box-shadow, 30
HUB, 251

dodatek

CoffeeScript, 215
Firebug, 234, 235
Firebug Lite, 233
Guard, 298
IE Developer Toolbar,

234

Selenium IDE, 243

dodawanie

cieni, 19
gradientu, 20
produktów, 116
zaokrgle, 19

dokumentacja

Backbone, 107
jQuery Mobile, 186

domieszki, mixin, 210
dostp do katalogu, 289
dymek, 26, 212
dynamiczne adowanie

treci, 183

dyrektywa DocumentRoot,

287

dzielenie treci na strony, 84

E

edytor Vim, 279–281, 284
efekt

fade, 36
poysku, 29

egzemplarz

LineInstance, 99
routera, 115

element

<blink>, 51
<blockquote>, 24, 27
<body>, 50

<center>, 51
<cite>, 24
<div>, 30, 43, 82
<footer>, 194
<header>, 194
<html>, 140
<img>, 29, 42, 195
<li>, 61
<link>, 165
<object>, 32
<script>, 81
<style>, 54
<tbody>, 98
<tfoot>, 103
<thead>, 98
meta viewport, 165
textarea, 142

F

faktura, 49, 56
faszywka, fake, 267
folder

_attachments, 156
_layouts, 201
_site, 203
bundles, 284
coffeescripts, 220
css, 204
Dropbox, 272
git_site, 223
image_cycling, 34
images, 205
Jasmine, 261
javascripts, 298
js, 205
sass, 209
statuses, 157

format

JSON, 90
JSONP, 144
PNG, 49
YAML, 202

formularz

HTML, 138
kontaktowy, 137, 139,

143

udostpniania folderu,

273

framework

CouchApp, 154
Evently, 160
Ruby on Rails, 305

funkcja

.fadeIn(), 62
.show(), 62
activateDialogFor(), 44
ajax(), 145
append_help_to(), 236
appendHelpTo(), 43
beforeEach(), 264
changePage(), 186
console.log(), 237
createTabs(), 63
cycle(), 36
displayHelpers(), 41,

44

displayHelpFor(), 44
displayTab(), 62
DomReady(), 268
dragPopup(), 175
event.preventDefault(),

69

event.stopPropagation(),

69

get(), 44
getCurrentPageNumber(),

76

getJSON(), 185
getNextPage(), 89
getQueryString(), 76
initialize(), 113, 118
jsonFlickrApi(), 145
ko.observable(), 99
loadData(), 88
loadMap(), 125

Kup książkę

Poleć książkę

background image

Skorowidz

313

loadPhotos(), 145
mail(), 140
nextPageWithJSON(),

88

observeMove(), 175
phpinfo(), 293
prependToggleAllLinks(),

68

pushState(), 91, 94
randomString(), 43
ready, 41
render(), 113, 117
replacePageNumber(),

77

scrollToEntry(), 75
scrollToPrevious(), 75
set_icon_to(), 238
setHelperClassTo(), 42
setIconTo(), 42
setupButtons(), 36
setupCreateClickEvent(),

266

slideDown(), 62
styleExamples(), 60, 63
success(), 115
to_html(), 80
toggleControls(), 36
toggleDisplayOf(), 44,

45, 46

toggleExpandCollapse(),

68

toJSON(), 113
updateBrowserUrl(), 94
updateContent(), 94
widget(), 151

funkcje

nawigacyjne, 73
przecigania, 171, 173
przewijania, 74
zwijania, 66
Sauce Labs, 260

G

ga new_feature, 230
gazie, 228
generator stron statycznych,

200

generowanie arkuszy stylów,

213

gradient tekstury, 20

H

HTML5, 13

I

identyfikator widget, 151
implementacja kart, 198
informacje

o bdach, 246
o tecie, 256

inspekcja elementów, 237
instalowanie

Apache, 277
CoffeeScriptu, 217
Gita, 223
Jekylla, 200
Ruby

w OS X, 306
w Ubuntu, 307
w Windows, 305

RVM, 306
Selenium Grid, 252

instrukcja

@import, 210
@include, 210
Given, 255
return false, 69
switch, 73

interaktywne

animacje, 189
prototypy, 191

interfejs

do zarzdzania

produktami, 108, 109

Highcharts, 130
koszyka, 96
uytkownika, 47

interfejsy interaktywne, 95
interpreter

CoffeeScriptu, 218
Ruby, 200, 305
RubyGems, 305

iteracja po tablicy, 83

J

Java Runtime Environment,

14

jzyk

CoffeeScript, 216, 221
HTML 4.01, 50
Makrdown, 202
Ruby, 14, 305
Sass, 208

jzyki

szablonowe, 109
znacznikowe, 202

jQuery, 13
jQuery Theme, 39
jQuery UI, 39
JSONP, JSON with

Padding, 144

K

karty, 59
kaskadowe arkusze stylów,

22

katalog

public, 134
sample_data, 135

klasa

button, 18
Cart, 101

Kup książkę

Poleć książkę

background image

314

Web development. Receptury nowej generacji

klasa

collapsed, 68
collapsible, 70
container, 193
delete, 120
disabled, 21
draggable, 175
entry, 72
examples, 60
expanded, 66
four columns, 199
help_link, 43
Highcharts, 134
LineItem, 98
loaded, 31
omega, 196
popup, 174
row, 196
scale-with-grid, 195
selected, 62
sheen, 30
View, 112

klauzula

Given, 253
Then, 253

klient SFTP, 278
kliknicie licia, 68
klucz

API, 250
niewymagajcy hasa,

286

SSH, 229

kod

formularza, 142
paginacji, 85
ródowy receptur, 15

kody klawiszy, 73
kolekcja produktów, 113
kolekcje, 111
kolumny, 195
komunikaty

o stanie serwerów, 159
o bdach, 160

konfiguracja

Apache, 277
ClickHeat, 240
Jasmine, 263
serwera WWW, 279
rodowiska testowego, 243

konkatenacja acuchów, 80
konstruktory obiektów, 98
konto

Cloudant, 153
Litmus, 48, 56
Sauce Labs, 248, 250

konwersja CoffeeScriptu, 220

L

liczba wpisów, 75
lista

nieuporzdkowana, 61,

202

pena, 67
produktów, 108, 164, 189
w iPhonie, 166
wpisów, 203
zaadowanych moduów,

293

ze zwinitymi gaziami,

67

zagniedona, 65

lokalizacja, 125
LTS, Long-term Support,

276

adowanie treci, 44
acuch sauce, 252
acuchy, 221
cze

Ajax, 90
do pliku, 34
Manage products, 245

czenie plików graficznych,

187

M

mapa

ciepa, 239–242
Google, 123
interaktywna, 124

maszyna wirtualna, 15, 229,

275, 278

mechanizm

przepisywania, 293
uwierzytelniania, 288
wdraania, 303

menu rozwijane, 168, 170
metoda

addProduct(), 120
ajax(), 107
append(), 79, 81
applyBindings(), 98
bind(), 120
click(), 258
clickAndWait(), 244
dependentObservable(),

100, 103

destroy(), 120
each(), 114
fetch(), 115
focus(), 78
getJSON(), 186
html(), 82
initialize(), 119
is_element_present(), 258
observableArray(), 101
pushState(), 95, 121
remove(), 103
render(), 113
renderProduct(), 120
save(), 119
serialize(), 70
stopPropagation(), 170
TDD, 269
to_html(), 80
type(), 258
url(), 111

Kup książkę

Poleć książkę

background image

Skorowidz

315

minimalizacja pliku, 297
modele widoków, 96, 97
modelowanie zbiorów

danych, 133

modu mod_rewrite, 291
muteks, 88

N

nagówek

HTTP 301 Redirect,

295

strony, 194

narzdzia

do testowania, 56
do tworzenia projektów,

154

narzdzie

bundler, 250
Capistrano, 304
Ceaser, 31
ClickHeat, 240
CTH, 249
Cucumber, 305
do wysyania plików, 203
Dropbox, 274
Firebug Lite, 234
Git, 222
Git Bash, 223
Guarda, 218
Jammit, 297
MiddleMan, 221
Pathogen, 284
Placehold.it, 195
Rake, 297, 301
RVM, 306
RVM Ruby, 308
sass, 209
SassOs X, 305
Sauce Labs, 249
Selenium Grid, 247, 252
Selenium Remote

Control, 247

nawigacja

dla

urzdze

przenonych, 169

do produktów, 185
po stronie, 71

NPM, Node Package

Manager, 218

numer strony, 76

O

obiekt

Cart, 101
DOM, 69
LineItem, 97, 101
Product, 111
window, 112

obiekty kolekcji, 112
obramowanie, 27
obrazy w wiadomociach

e-mail, 57

obserwacja zdarze

dotykowych, 177

obsuga

bdów, 143
cieni, 197
CouchDB, 153
Firebuga, 235
lici, 68
cza, 118
przezroczystoci, 211
skrótów klawiszowych,

71

SSL, 285, 286
zdarze, 63, 96, 118

odwracanie gradientu, 20
okno

dialogowe, 39
draggable_window, 175
modalne, 41
powoki, 201
przegldarki, 193
Selenium IDE, 244

opcje modalnoci, 44
operator

#, 83
->, 216

organizacja certyfikacyjna

Thawte, 287
VeriSign, 287

P

paginacja, 85
parametr

page, 93
start_page, 93

pisanie widoków, 79
plik

.htaccess, 289, 291
.htpasswd, 289
_buttons.scss, 210
_config.yml, 205
_mixins.scss, 213
_speech_bubble.scss,

212

about_us.html, 226
add_todo.js, 266
add_todo_spec.js, 261
app.js, 109, 110, 219
assets.yml, 299
base.html, 201
buttons.scss, 209
contact.html, 206
contact.markdown, 206
contact.php, 138
cucumber.yml, 251
endless_pagination.js, 85
expand_collapse_sprite.

png, 187

form.coffee, 303
Guard, 302
Guardfile, 220, 299
helper-text-broken.js,

236

hosts, 251

Kup książkę

Poleć książkę

background image

316

Web development. Receptury nowej generacji

plik

index.html, 15, 110, 179
iPhone.css, 165
layout.css, 196
map.js, 157
mixins.scss, 210
mustache.js, 219
mustachejs.js, 159
ondemand.yml, 250
page.html, 206
post.html, 204
products.html, 85, 226
Rake, 302
reduce.js, 157
rotate.js, 34
server.bat, 15
SpecRunner.html, 261,

263

style.css, 165, 204

pliki

CSS, 208
Sass, 208
wpisów, 203
Youth Technology

Days, 273

pobieranie

danych, 144, 157
zdj, 145

podmienianie istniejcego

systemu, 81

podzia na strony, 76
pokaz slajdów, 33
pole wyszukiwania, 72, 77
polecenia powoki, 14
polecenie

a git status, 224
cat, 289
chmod, 240
clickAndWait(), 245
couchapp, 157
git, 230
git stash list, 227
git status, 225

htpasswd, 289
jekyll, 207
scp, 141

potwierdzenie wysania

danych, 300

powiadomienia o bdach,

142, 246

powoka, 14
prekompilator, 208
program

Cyberduck, 278
ssh-keygen, 229
Vim, 279
VirtualBox, 275
VMware, 279

programowanie

behawioralne, 248

prototyp

jQuery.fn, 67
projektu, 191

przechowywanie

danych, 136
hase w skryptach, 303
listy produktów, 182

przechwytywanie zdarze,

73

przeciganie okienka, 172
przecianie serwera, 85
przecinek, 118
przedrostek

-moz-*, 20
-o-*, 20
-webkit-*, 20

przegldanie produktów,

182

przegldarka IE 8, 90
przegldarki do testowania,

252

przejcia, 28, 37
przekierowanie, 292
przeczanie kart, 61
przewijanie, 74
przezroczysto, 211

przycisk

Wstrzymaj, 37
Wznów, 37

przyciski bez ikon, 181
pseudoklasa hover, 31
punkt przywracania, 279

Q

QEDServer, 14, 85

R

regua

konfiguracyjna, 283
RewriteRule, 294

rejestrowanie, 244
relacyjne bazy danych, 154
renderowanie

szablonu, 80
widoku dla obiektu, 112

repozytorium Git, 224
resetowanie ustawie

elementów, 19

rodzaje certyfikatów SSL,

288

rola, 102

button, 180
controlgroup, 180

router ProductsRouter, 114
rozgazienia, 225
rozmiar

mapy, 125
okna przegldarki, 193

rozszerzenie Firebug, 234
rozwijanie wzów listy, 68
RVM, Ruby Version

Manager, 306

rysowanie wykresu, 136

S

scenariusze, scenario, 253
sekcja <head>, 54

Kup książkę

Poleć książkę

background image

Skorowidz

317

selektor

before, 25
after, 25

serwer

Apache, 288
CouchDB, 158
Git, 228
QEDServer, 134
WEBrick, 203

serwis

Cloudant.com, 153
GitHub, 80, 207, 231,

261

HTML5 Rocks, 177
JSFiddle.net, 136
Litmus.com, 48
MailChimp, 58
MLS, 192

siatka Skeletona, 193
Skeleton, 192
skadnia CoffeeScriptu, 216
skadniki Backbone, 107
skróty klawiszowe, 72, 78
skrypt paginacji, 91
SNI, Server Name

Indication, 288

sprite’y w CSS, 187
statyczne strony, 296
stopniowe ulepszanie, 70
strona

bdu, 282
bdu 404, 280
kodowa UTF-8, 90
produktów, 184

strony statyczne, 206
struktura

folderów, 262
Skeletona, 192

stuknicie odnonika, 169
styl

animacji, 46
slide, 46

stylizowanie

cytatów, 21
elementów, 18
kart, 63
okienek pomocy, 38
okna dialogowego, 42
poysku, 32
przycisków, 17

symbol =>, 303
system

Compass, 199
Git, 236
Linux Ubuntu Server,

275

Mustache, 79
Ubuntu, 276
Ubuntu 10.04 Server,

275

systemy siatkowe, 192
szablon

domylny Skeletona, 198
faktury, 50

nagówek, 51
stopka, 53
tabele, 51
tre, 52

listy, 112
strony, 34

szablony

MailChimp, 58
Mustache, 84, 219
wewntrzne, 82

szkielet

Jasmine, 261
RSpec, 261
strony, 85
testowy, 261

szpieg, 267

ledzenie

aktywnoci

uytkowników, 239

zdarze kliknicia, 169,

240

zmian w adresie URL,

115

T

tablica

$_POST, 140
$errors, 141, 142
ages, 136
elementów, 101
items, 104
photos, 146

test, 243
testowanie, 257

behawioralne, 261
biblioteki jQuery

Mobile, 182

formularza

kontaktowego, 141

kodu JavaScript, 260
przegldarek, 242
stron, 247
wiadomoci e-mail, 48,

56

testy

Cucumber, 248, 253
Jasmine, 268

transformacje, 32
transformacje CSS3, 28
trasa

#new, 117
domylna, 114

tre na kartach, 59
tryb wstawiania, 282
tryby dziaania Vim, 281

Kup książkę

Poleć książkę

background image

318

Web development. Receptury nowej generacji

tworzenie

animacji, 28
aplikacji CouchApp,

156

atrapy danych, 264
bazy danych, 154
bloga, 200
dynamicznych stron, 201
elementów <div>, 87
faktury, 49
folderu statuses, 156
formularza HTML, 138
grafów, 130
interfejsów, 178
kart, 60
listy produktów, 111
makiety, 193
mapy, 126
maszyny wirtualnej, 275
modelu produktu, 108
modularnych arkuszy

stylów, 207

nowego produktu, 116
oprogramowania, 269
podpisanego certyfikatu,

285

pokazu slajdów, 33
profili uytkowników,

133

projektu Sass, 208
prototypów, 191
routera, 114
stron, 180
stron bdów, 282
struktury plików, 201
szablonów HTML, 79
testu, 243
testu zaawansowanego,

246

wiadomoci e-mail, 47
widoku, 157
widetów, 147

wpisów, 202
wykresów, 129
znaczników, 126

typ sieci, 276

U

udostpnianie

folderu, 272
widetu, 152

ukad strony, 193
ukady pojedynczych

wpisów, 204

ukrywanie kart, 61
urzdzenia przenone, 163
usuga

Campaign Monitor, 54
chmurowa, 249
Dropbox, 272, 274
MailChimp, 54
Sauce Labs, 251
Sauce Labs

OnDemand, 250

testowania Selenium,

249

ustawienie typu sieci, 276
usuwanie

cieni, 197
produktów, 103, 120
wirujcego kóka, 89

uwierzytelnianie HTTP,

289, 290

W

wczytywanie mapy, 125
wzy licie, 68
wiadomoci e-mail, 47–49
wiadomo wieloczciowa,

54

wizania przepywu

sterowania, 100

wizanie

obiektów, 100
zdarzenia i funkcji, 103

widok

ListView, 119
ProductView, 112

widoki

Backbone, 106, 112
CouchDB, 157

widety, 147
wielokrotne

wczytywanie treci, 44
wykorzystanie kodu, 210

wirtualny serwer, 277
wirujce kóko, 89
wasnoci, feature, 253
wasno

border-radius, 27
box-shadow, 213
content, 27
linear-gradient, 27
notes, 83
plotOptions, 133
quantity, 99
series, 131
shiftKey, 78
transition, 30
z-index, 25

wspórzdne

geograficzne, 126
pooenia obrazu, 188

wspóuytkowanie folderu,

273

wstawianie mapy Google, 123
wtyczka

CouchDB, 159
Cycle, 33
guard-coffeescript, 220
Jasmine-jQuery, 261

wykres, 129
wykres koowy, 132
wyskakujce okienko, 174

Kup książkę

Poleć książkę

background image

Skorowidz

319

wysyanie

gazi, 230
plików, 277
wiadomoci e-mail, 139

wywietlanie

danych klientów, 135
informacji, 128
listy produktów, 116
testów, 256
treci, 58
wiadomoci, 158

Z

zabezpieczanie

serwera Apache, 284
treci, 288

zachowanie czy, 292
zagniedanie

konstrukcji, 198
regu, 212
selektorów, 212

zapytania o media CSS,

164, 167, 196

zarzdzanie plikami, 222
zalepka, stub, 267
zdalny serwer, 144

Git, 228

zdarzenia

dotykowe, 175
onchange, 121
w widoku, 118

zdarzenie

add, 119
click(), 266
hover, 169
kliknicia, 69
mousemove, 175
mouseup, 175
submit, 70, 185
tap, 185
touchend, 172
touchmove, 177
touchstart, 172, 176

zdjcia, 145
zmienianie adresu URL,

91, 114

zmienna

chartOptions, 131
current_entry, 74
currentPage, 93
data, 80
el, 117
nextPage, 88
page_number, 77

rendered, 80
tabTitle, 62
template, 113
todo, 265
treshold, 90

zmienne globalne, 87
znaczniki szablonowe, 201
znak

\, 259
#, 92, 114
$, 67, 209
?, 77, 94

znaki ==, 238
zwijanie, 66
zwijanie wzów listy, 68

danie

DELETE, 108
GET, 82, 108
getJSON(), 183
POST, 70, 108
PUT, 108

Kup książkę

Poleć książkę

background image

320

Web development. Receptury nowej generacji

Kup książkę

Poleć książkę

background image
background image

Wyszukiwarka

Podobne podstrony:

więcej podobnych podstron