Eri selaimien ja selainversioiden kanssa tapellessa jQuery helpottaa Front-end-koodarin elämää valtavasti. jQuery on suuri tuskan poistaja esimerkiksi Ajax:in kanssa temppuillessa, mutta silti on vielä joitakin sudenkuoppia, mitä sivunrakentajan on syytä varoa.
Tämä opas on henkinen jatko-osa jutulle nimeltään Ajax:in alkeet jQueryn avulla. Demosivu muistuttaa pitkälti edelliskertaista sivua, mutta joitakin muutoksia on tullut:
01.
<!DOCTYPE html>
02.
<
html
lang
=
"fi"
>
03.
04.
<
head
>
05.
<
meta
charset
=
utf
-8>
06.
<
title
>Otsikko</
title
>
07.
08.
<
script
src
=
"http://www.google.com/jsapi"
></
script
>
09.
</
head
>
10.
11.
<
body
>
12.
13.
<
h1
>Otsikko</
h1
>
14.
15.
<
ul
id
=
"navigointi"
>
16.
<
li
><
a
id
=
"etusivu"
href
=
"#"
>Etusivu</
a
></
li
>
17.
<
li
><
a
id
=
"uutiset"
href
=
"#"
>Uutiset</
a
></
li
>
18.
<
li
><
a
id
=
"yhteystiedot"
href
=
"#"
>Yhteystiedot</
a
></
li
>
19.
</
ul
>
20.
21.
<
div
id
=
"sisalto"
>
22.
23.
</
div
>
24.
25.
</
body
>
26.
</
html
>
Kaikki sisältö on siirretty yhteen dokumenttiin nimeltään ajax.html, jotta jatkossa osioiden käsittely jQueryllä olisi hiukan helpompaa. Heitetään soppaan vielä mukaan pieni kuvagalleria jokaiselle osiolle:
01.
<
div
id
=
"etusivu"
>
02.
<
h2
>Etusivun jutut</
h2
>
03.
04.
<
p
>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...</
p
>
05.
06.
<
ul
id
=
"kuvalinkit"
>
07.
<
li
><
a
href
=
"#"
class
=
"kuva1"
>Kuva 1</
a
></
li
>
08.
<
li
><
a
href
=
"#"
class
=
"kuva2"
>Kuva 2</
a
></
li
>
09.
<
li
><
a
href
=
"#"
class
=
"kuva3"
>Kuva 3</
a
></
li
>
10.
</
ul
>
11.
12.
<
div
id
=
"galleria"
>
13.
<
div
class
=
"kuva1"
></
div
>
14.
<
div
class
=
"kuva2"
></
div
>
15.
<
div
class
=
"kuva3"
></
div
>
16.
</
div
>
17.
</
div
>
18.
19.
<
div
id
=
"uutiset"
>
20.
<
h2
>Uutiset</
h2
>
21.
22.
<
p
>Päivän tärkeimmät tapahtumat.</
p
>
23.
24.
<
ul
id
=
"kuvalinkit"
>
25.
<
li
><
a
href
=
"#"
class
=
"kuva1"
>Kuva 1</
a
></
li
>
26.
<
li
><
a
href
=
"#"
class
=
"kuva2"
>Kuva 2</
a
></
li
>
27.
<
li
><
a
href
=
"#"
class
=
"kuva3"
>Kuva 3</
a
></
li
>
28.
</
ul
>
29.
30.
<
div
id
=
"galleria"
>
31.
<
div
class
=
"kuva1"
></
div
>
32.
<
div
class
=
"kuva2"
></
div
>
33.
<
div
class
=
"kuva3"
></
div
>
34.
</
div
>
35.
</
div
>
36.
37.
<
div
id
=
"yhteystiedot"
>
38.
<
h2
>Yhteystiedot</
h2
>
39.
40.
<
p
>Osoite, puhelinnumero yms...</
p
>
41.
42.
<
ul
id
=
"kuvalinkit"
>
43.
<
li
><
a
href
=
"#"
class
=
"kuva1"
>Kuva 1</
a
></
li
>
44.
<
li
><
a
href
=
"#"
class
=
"kuva2"
>Kuva 2</
a
></
li
>
45.
<
li
><
a
href
=
"#"
class
=
"kuva3"
>Kuva 3</
a
></
li
>
46.
</
ul
>
47.
48.
<
div
id
=
"galleria"
>
49.
<
div
class
=
"kuva1"
></
div
>
50.
<
div
class
=
"kuva2"
></
div
>
51.
<
div
class
=
"kuva3"
></
div
>
52.
</
div
>
53.
</
div
>
Kirjoitetaan navigoinnista vastaava jQuery uusiksi:
01.
google.load("jquery", "1.4.2");
02.
google.setOnLoadCallback(function() {
03.
04.
// Ladataan etusivun sisällöt näkyviin
05.
$('#sisalto').load('ajax.html #etusivu');
06.
07.
// Vaihdetaan näkymää klikatun linkin mukaan
08.
$('#navigointi a').click( function() {
09.
10.
$('#sisalto').load('ajax.html #' + $(this).attr('id'));
11.
12.
return false;
13.
14.
});
15.
16.
});
Seuraavaksi voimmekin jatkaa edellisen perään galleriamme toiminnallisuus. Logiikka on pitkälti sama, kuin aiemminkin:
01.
google.load("jquery", "1.4.2");
02.
google.setOnLoadCallback(function() {
03.
04.
// Ladataan etusivun sisällöt näkyviin
05.
$('#sisalto').load('ajax.html #etusivu');
06.
07.
// Vaihdetaan näkymää klikatun linkin mukaan
08.
$('#navigointi a').click( function() {
09.
$('#sisalto').load('ajax.html #' + $(this).attr('id'));
10.
return false;
11.
});
12.
13.
// Avaa klikattu kuva ja piilota edellinen
14.
$('#kuvalinkit a').click( function() {
15.
16.
$('#galleria .' + $(this).attr('class')).show('slow')
17.
.siblings()
18.
.hide('slow');
19.
20.
return false;
21.
22.
});
23.
});
Ken vanhoja muistaa, sitä tikulla silmään
Kun selain on saanut ladattua sivun rakenteen, DOM:in, jQuery käy sen läpi ja lisää mm. klikkausten tapahtumakäsittelijät (click event handlers) vaadituille elementeille, meidän tapauksessamme kuvalinkeille. Kun lataamme Ajax-kutsulla #sisalto-diviin jonkin sisältönäkymistä, muokkaamme tätä rakennetta jälkeenpäin. jQuery ja JavaScript ovat tällä hetkellä hieman ulalla, sillä kukaan ei ole kertonut heille, että sivuilla on jotain tapahtunut. Meidän täytyy siis kertoa JavaScriptille jotenkin, että sivu on päivittynyt ja sen täytyy ottaa huomioon myös uusi sisältö.
Kun ei homma itseltä onnistu, delegoidaan
jQueryn tuorein päivitys, 1.4.2, toi mukanaan uuden .delegate()-metodin, jolla saamme ongelmamme ratkaistua. Delegate-metodin toimintaperiaate ei välttämättä aukea aivan heti kaikille joten otetaanpa alkuun pieni annos JavaScriptin teoriaa:
Tapahtumien kupliminen, tai event bubbling, on olennainen osa koko JavaScriptin filosofiaa. Kun käyttäjä klikkaa elementtiä sivuilla, alkaa taustalla erikoinen tapahtumaketju. Katsotaan vaikka esimerkiksi demosivumme linkkilistaa: Klikatessa linkkiä listassa, laukeaa klikkaustapahtuma tässä kyseisessä HTML-elementissä. Tämän jälkeen linkkielementti ”mainostaa” tätä tapahtumaa isäntänään olevalle LI-elementille. LI-elementti taas heittää tämän viestin ylöspäin UL-elementille ja näin jatketaan ylöspäin aina dokumenttipuun alkuun asti, ellei kuplimista jostain syystä erityisesti haluta katkaista.
Delegate-metodin temppuna on hakea jokin ylempi elementti sivuilta ja sitoa kuplimisen kautta jonkin alempana dokumenttipuussa olevan elementin tapahtuma, tässä tapauksessa klikkaus, siihen. Jotta saisimme delegate-metodin käyttöömme, pitää meidän valita sivuilta jokin kaikille linkeille yhteinen elementti, jota ei päivitetä Ajax-kutsuja tehdessä. Body on useasti aika varma valinta. Käytämme body:a hyväksemme kierrättämällä klikkaustapahtumat sen kautta ja delegoimme tapahtumat alaspäin uusille, Ajax:lla tuoduille elementeille.
Muutetaan alkuperäisiä kuvanvaihtolinkkiemme tapahtumakäsittelijöitä hiukan niin, että otamme delegate-metodin mukaan leikkeihin:
1.
// Avaa klikattu kuva ja piilota edellinen
2.
$('body').delegate('#kuvalinkit a', 'click', function() {
3.
$('#galleria .' + $(this).attr('class')).show('slow')
4.
.siblings()
5.
.hide('slow');
6.
return false;
7.
});
Mitä suuremmaksi Ajax-projektit kasvavat, sitä arvokkaammaksi suorituskyvyn parantajaksi delegate nousee. Vanhemmissa jQuery-versioissa käytetty live()-metodin perusidea on pitkälle sama, kuin delegatella, mutta se sitoo tapahtumakäsittelijät aina dokumentin alkuun. Delegatella voimme sitoa klikkausten seurannan mahdollisimman lähelle klikkauksen alkujuuria ja näin vähentää selaimen taakkaa JavaScriptin käsittelyssä.