Ostatnie lata przyniosły wiele zmian, jeżeli chodzi o sposób tworzenia serwisów WWW. Zaczęto stosować technikę AJAX, która umożliwia interakcję między użytkownikiem a serwerem bez konieczności przeładowywania całej strony. W dużej mierze odpowiada za to rozbudowany język obiektowy JavaScript, który został wyposażony w liczne biblioteki ułatwiające pisanie w nim skryptów. Jedną z najciekawszych jest biblioteka jQuery.
Pierwsze kroki
Biblioteka jQuery upraszcza wykonanie dotychczas całkiem skomplikowanych rzeczy. Mamy wrażenie, że korzystamy z języka o zupełnie nowej jakości.
Aby zacząć przygodę z jQuery, najpierw musimy pobrać najnowszą jej wersję ze strony: http://jquery.com. Następnie w pliku (X)HTML w sekcji {html}{/html} umieszczamy stosowne odwołanie do biblioteki:
W naszym przypadku jquery.js to nazwa pobranego pliku z jQuery, który umieściliśmy w tym samym katalogu co plik z kodem (X)HTML.
W dalszej części będziemy zakładać, że kod (X)HTML naszej strony ma postać jak na listingu 1.
Newsletter
Newsletter to elektroniczny biuletyn – czasopisma rozsyłane przez nas za pomocą poczty elektronicznej do prenumeratorów. Zapisując się na nasz newsletter masz gwarancję, że nie przegapisz żadnej ważnej informacji. Obiecujemy, że na podany adres e-mail nie będziemy wysyłać żadnych reklam. Oczywiście subskrypcja jest całkowicie bezpłatna i w każdej chwili możesz z niej zrezygnować.
Imię | Nazwisko |
---|---|
Jacek | Nowak |
Ania | Piotrowska |
Wojtek | Kowalski |
Natomiast zawartość pliku ze stylami (style.css), które będziemy wykorzystywać w artykule, przedstawia się tak jak na listingu 2.
.important {
color: red;
}
.odd {
background-color: grey;
}
.even {
background-color: yellow;
}
Strona jest zatem bardzo prosta, zawiera dwa akapity tekstu, formularz, tabelkę i kilka linków. Wizualnie nie wygląda to zbyt dobrze (rys. 1), treść także jest dość przypadkowa. Jednak w tym przypadku jest to tylko przykładowy plik, na którym będziemy testować różne funkcje udostępniane przez bibliotekę jQuery.
Szczególną uwagę należy zwrócić na umieszczony w sekcji {html}{/html} kod:
Wszystko, co znajduje się wewnątrz konstrukcji {stala}$(document).ready(){/stala}, wykonywane jest zaraz po wczytaniu DOM danej strony. Przekładając to na prostszy język – kod JavaScript wykonywany jest bez zbędnego opóźnienia, jeszcze przed załadowaniem całej grafiki. Zatem {stala}$(document).ready(){/stala} to w jQuery korzystniejsza wersja tradycyjnego {html}{/html} (chociaż można korzystać z jej wiernego odpowiednika: {stala}$(document).load(){/stala}). Natomiast samo słowo kluczowe function służy do tworzenia tzw. funkcji anonimowej. Jest to właściwość dostępna w samym języku JavaScript i intensywnie wykorzystywana w jQuery.
Następnie nasz kod umieszczamy w miejscu wskazywanym przez komentarz {html}/* miejsce na kod jQuery */{/html}.
AJAX
jQuery bardzo ułatwia tworzenie skryptów wykorzystujących AJAX. Udostępnia mianowicie zestaw funkcji, które opakowują cały proces łączenia się ze zdalnym serwerem, wysyłania danych i odbierania wiadomości zwrotnej. Nie musimy martwić się o cały, dość żmudny proces implementacji takiego mechanizmu, uwzględniania różnic w obsłudze obiektu XMLHttpRequest (kręgosłupa całego mechanizmu) w zależności od przeglądarki internetowej itp.
Na naszej przykładowej stronie mamy formularz z miejscem na wpisanie adresu e-mail. Załóżmy, że chcemy, aby wpisywany tam adres był unikalny. W przypadku stwierdzenia, że w naszej \”bazie\” znajduje się dany e-mail, powinien wyświetlać się odpowiedni komunikat błędu. Standardowy sposób wykonania takiego zadania to po prostu sprawdzanie unikalności danego adresu dopiero po wysłaniu formularza.
Jednak rozwiązanie to jest trochę ułomne – klient najpierw musi wypełnić wszystkie pola, następnie strona jest przeładowywana i dopiero wtedy dowiaduje się, że coś poszło nie tak. Wykorzystajmy zatem AJAX, aby adres e-mail był sprawdzany w tle, od razu po wypełnieniu pola – bez zbędnego odświeżania strony. Odpowiedni kod w jQuery przedstawia się tak:
$(\'#cemail\').blur(function() {
$.get(\'email.php\', { email: $(this).val() },
function(data){
if (data == \'error\') {
alert(\"Podany e-mail jest już zajęty!\");
}
})
}
);
Do zdarzenia onblur, które jest wywoływane w momencie przejścia użytkownika z jednego pola formularza do innego, przypisana została funkcja anonimowa odpowiedzialna za sprawdzanie unikalności wpisanego adresu e-mail. W jej wnętrzu wywołujemy wbudowaną w jQuery funkcję {stala}$.get(){/stala}. Jako pierwszy argument podajemy plik ze skryptem (email.php), do którego chcemy przesłać określone dane. Na drugim miejscu umieszczamy nazwy przekazywanych parametrów i ich wartości.
W naszym przykładzie jest to pojedynczy parametr zawierający wpisany do formularza adres e-mail. Ostatnim parametrem jest funkcja, która odbiera treść zwróconą przez email.php i w zależności od jej zawartości wykonuje odpowiednie działanie.
Plik email.php zawiera maksymalnie prosty kod w języku PHP:
Jeżeli wpiszemy do formularza adres e-mail redakcja@mi.com.pl, to skrypt zwróci komunikat \”error\”, co spowoduje pojawienie się w przeglądarce komunikatu \”Podany e-mail jest już zajęty\” (rys. 2). Oczywiście w rzeczywistej aplikacji zawartość pliku email.php będzie dużo bardziej rozbudowana. Konieczne okaże się chociażby połączenie z bazą danych, z listą prenumeratorów – w celu sprawdzenia, czy adres jest wolny czy nie.
Analogicznie jak funkcja {stala}$.get(){/stala} działa {stala}$.post(){/stala}. Jak łatwo się domyśleć, różnią się one tylko sposobem przesyłania danych – w pierwszym przypadku jest to metoda GET, a w drugim – POST. Innymi funkcjami, które można wykorzystać do komunikacji jQuery ze skryptami na danym serwerze, są: {stala}$.ajax(){/stala}, {stala}$.load(){/stala}, {stala}$.getScript(){/stala}, {stala}$.getJSON(){/stala}. Każda z nich różni się nieco działaniem i przeznaczeniem. Dokładne informacje na ich temat można znaleźć w oficjalnej dokumentacji dostępnej na stronie: http://docs.jquery.com/ajax.
Selektory
Za pomocą selektorów możemy wskazać dany element lub grupę elementów należących do modelu DOM danej strony. Tymi elementami są po prostu znaczniki (X)HTML, ich zawartość, posiadane atrybuty itp. Selekcji możemy dokonać posługując się selektorami znanymi ze specyfikacji CSS, jak i używając języka XPath. Dodatkowo autorzy jQuery przygotowali kilka rozwiązań dedykowanych tylko dla ich biblioteki.
Zacznijmy od najprostszych przykładów. Załóżmy, że chcielibyśmy wskazać na nasz nagłówek {html}{/html}. Dokonujemy tego za pomocą instrukcji:
$(\'h1\')
bądź bardziej precyzyjnie:
$(\'#container h1\')
W drugim przypadku mamy gwarancję, że nie zostaną wybrane elementy {html}{/html}, które umieszczone byłyby poza {html}
Wskazaliśmy nasz nagłówek, ale trzeba to jakoś wykorzystać. Możemy zrobić coś takiego:
$(\'#container h1\').addClass(\'important\');
Funkcja {stala}addClass(){/stala} działa na wskazanych przez nas elementach (nie musi być to bowiem tylko jeden nagłówek) i dodaje do nich klasę o podanej nazwie. W naszym przypadku klasa important zdefiniowana jest w pliku style.css – ustawia ona po prostu kolor tekstu na czerwony.
Załóżmy, że chcielibyśmy dodać określoną klasę do akapitu. Aby utrudnić sobie zadanie, załóżmy, że chcemy ją przypisać jedynie do pierwszego występującego znacznika {html}
{/html}:
$(\'p:first\').addClass(\'important\');
Wykorzystaliśmy w tym celu filtr {stala}:first{/stala}, który wybiera jedynie pierwszy element z grupy wybranych przez dany selektor. Bardziej uniwersalne działanie ma filtr {stala}:eq(){/stala}. Powyższy kod można by zastąpić czymś takim:
$(\'p:eq(0)\').addClass(\'important\');
W przypadku chęci wybrania drugiego akapitu zmienilibyśmy {stala}:eq(0){/stala} na {stala}:eq(1){/stala} – warto zatem pamiętać, że numeracja zaczyna się od 0.
Jak wskazać elementy zawierające określony atrybut? Za pomocą konstrukcji element[@parametr]. Pogrubimy zatem tekst zawarty w znacznikach {html}
$(\'label[@for]\').css({\'font-weight\': \'bold\'});
Pójdziemy jeszcze dalej. Na naszej stronie chcielibyśmy wyróżnić linki kierujące do innych serwisów. Zakładamy bowiem, że odnośniki do podstron zapisujemy w postaci względnej (np. {stala}onas.html{/stala}). Za pomocą odpowiedniego selektora wybierzemy elementy {html}{/html} z atrybutem href rozpoczynającym się od liter \”http://\”, a następnie zmienimy ich kolor na zielony:
$(\'a[@href^=http://]\').css({\'color\': \'green\'});
Jak wiemy, za pomocą konstrukcji element[@parametr] wskazujemy elementy zawierające określony atrybut. Z kolei {stala}^={/stala} dopasowuje początek wartości danego parametru z określonym ciągiem znaków. $= działa analogicznie, ale w odniesieniu do końca atrybutu, a {stala}$={/stala} dowolnego jego fragmentu. Zatem dodanie stylów do linków kierujących do plików z określonym rozszerzeniem jest równie proste:
$(\'a[@href$=.html]\').css({\'color\': \'yellow\'});
To są mało skomplikowane przykłady. O wiele bardziej rozbudowane rzeczy można uzyskać łącząc kolejne funkcje w jeden łańcuch. Każda z takich instrukcji korzysta z wyniku otrzymanego przez tę, która ją poprzedza. Najlepiej pokazać to na jakimś przykładzie.
Na naszej stronie mamy tabelę. Aby poprawić jej wygląd, chcielibyśmy pokolorować poszczególne wiersze – na inny kolor parzyste i nieparzyste. Jednak nasz selektor ma nie dotyczyć wiersza {html}
{/html} zawierającego komórki {html}{/html}, a więc naszego nagłówka. Można to osiągnąć na kilka sposób, chociażby tak:
$(\'td\').parent().filter(\':odd\').addClass(\'odd\');
$(\'td\').parent().filter(\':even\').addClass(\'even\');
Najpierw wybieramy wszystkie komórki {html}{/html} naszej tabeli. Następnie za pomocą funkcji {stala}parent(){/stala} wskazujemy na ich rodziców – w naszym przypadku są to po prostu wiersze {html}
{/html}. Następnie lista wierszy jest filtrowana. W pierwszym przypadku wybierane są tylko parzyste, a w drugim wyłącznie nieparzyste. Dalsza część powinna być już jasna. Po prostu dodajemy do otrzymanego wyniku stosowne klasy.
Kolejny ciekawy przykład:
$(\'td:contains(\"Wojtek\")\').next().addClass(\'important\');
Tym razem wybieramy wszystkie komórki zawierające słowo \”Wojtek\”. Następnie za pomocą funkcji {stala}next(){/stala} wskazujemy elementy sąsiadujące z nimi i nadajemy im odpowiednią klasę. W naszym przykładzie element {html}Kowalski
{/html} będzie od tego momentu widziany jako {html}Kowalski
{/html}.
Zdarzenia
Jednym ze zdarzeń, które już poznaliśmy, jest {stala}onload(){/stala}. W zastosowaniu do elementu {html}{/html} wskazuje na rzeczy, które mają zostać wykonane po załadowaniu strony. Jak wiemy, w jQuery najczęściej stosowanym odpowiednikiem dla {stala}onload(){/stala} jest {stala}$(document).load(){/stala}. W bardzo prosty sposób możemy podłączać funkcje pod zdarzenia dostępne w modelu DOM.
Nasza przykładowa strona zawiera dwa akapity (tekst w znacznikach {html}{/html}). Przypuśćmy, że chcielibyśmy wyświetlać tylko pierwszy z nich, a drugi powinien pojawiać się dopiero po kliknięciu linku więcej. Pierwsze, co musimy zrobić, to ukryć drugi akapit:
$(\'p:gt(0)\').hide();
Jak widać, funkcja {stala}hide(){/stala} odpowiada za ukrycie danego elementu. To po prostu odpowiednik dyrektywy display: none w CSS. Jednak o tyle mądrzejszy, że zapamiętuje bieżącą wartość display, która zwykle przyjmuje wartość inline lub block. Zatem funkcja odwrotna {stala}show(){/stala} poprawnie przywraca dany element do stanu sprzed zastosowana {stala}hide(){/stala}. Filtr {stala}:gt(){/stala} różni się od {stala}:eq(){/stala} tym, że wskazuje na elementy których numer jest większy od podanego jako argument. W związku z tym, że nasza strona zawiera tylko dwa akapity, moglibyśmy ograniczyć się do {stala}:eq(1){/stala}, jednak dzięki {stala}:gt(0){/stala} zabezpieczamy się na wypadek dodania kolejnych.
Kolejną rzeczą, którą musimy zrobić, jest dodanie na końcu pierwszego akapitu elementu z tekstem \”więcej\”. W tym celu posłużymy się nieużywaną jeszcze funkcją {stala}appendTo(){/stala}, która dodaje podany kod (X)HTML do elementów wskazywanych przez zadany selektor:
$(\'więcej\').appendTo(\'p:first\');
Przechodząc jednak do meritum, dodamy zdarzenie typu {stala}onclick(){/stala} do znacznika {html}{/html}:
$(\'span.more\').click(function() {
$(\'p:gt(0)\').show();
$(this).hide();
});
Za pomocą {stala}show(){/stala} wyświetlamy ponownie ukryty akapit. Z kolei {stala}$(this){/stala} wskazuje na kliknięty element (zawierający tekst \”więcej\”), który oczywiście chowamy, bo nie jest nam już potrzebny.
Teraz zajmiemy się dodaniem zdarzenia do prostego formularza na naszej stronie. Mamy w nim dwa elementy {html}
{/html} typu checkbox, do których przypisane są etykiety \”akceptuję regulamin\” oraz \”chcę otrzymać newsletter\”. Zrobimy tak, aby po zaznaczeniu danego checkboxa tekst odpowiadającej mu etykiety był pogrubiany. Oczywiście, po odznaczeniu wszystko powinno wracać do pierwotnego stany. Działający kod wygląda tak:
$(\'input:checkbox\').bind(\'click\', function() {
if ($(this).is(\':checked\')) {
$(this).parent().css({\'font-weight\': \'bold\'});
}
else {
$(this).parent().css({\'font-weight\': \'normal\'});
}
});
Za pomocą filtra {stala}:checkbox{/stala} wybieramy jedynie te elementy {html}
{/html}, które są typu checkbox (identycznie zadziałałoby {stala}$(\’input[type=checkbox]\’){/stala}). Funkcja bind() to bardziej uniwersalny sposób definiowania zdarzeń. Jako pierwszy argument przyjmuje nazwę zdarzenia, a jako drugi – funkcję, która ma zostać wykonana w momencie jego wystąpienia. Nową konstrukcją jest jeszcze is(). Pozwala ona wskazać dodatkową własność, którą musi spełniać dany element – w tym wypadku musi być on zaznaczony (filtr {stala}:checked{/stala}).
Efekty
jQuery zawiera zestaw funkcji, za pomocą których możemy dodać do naszej strony ciekawe efekty wizualne. Utworzyliśmy zdarzenie odpowiedzialne za wyświetlanie dodatkowego akapitu. Jednak pojawia się on natychmiast po kliknięciu \”więcej\” – brakuje stonowanego przejścia. Dodajmy zatem efekt płynnego \”wynurzania się\” ukrytego akapitu:
$(\'p:gt(0)\').show(\'slow\');
Przekazaliśmy po prostu do funkcji show() słowo kluczowe \”slow\”. Oznacza to, że od momentu wywołania zdarzenia do pojawienia się całego akapitu mija 0,6 sekundy. Funkcja {stala}show(){/stala} może przyjmować takie wartości jak: \”slow\”, \”normal\” oraz \”fast\”, a także konkretną liczbę wskazującą czas w milisekundach.
A teraz wypróbujmy coś takiego:
$(\'p:first\').hide().fadeIn(1500);
Po wczytaniu strony najpierw pierwszy akapit jest ukrywany (funkcja hide()). Następnie zwiększa się jego nieprzezroczystość (ang. opacity): od wartości 0 (tekst zupełnie niewidoczny), poprzez wartości pośrednie, aż do momentu jego pełnej widoczności. Cały efekt trwa 1500 milisekund czyli 1,5 sekundy.
Innymi funkcjami, za pomocą których można na różne sposoby ukrywać lub pokazywać wybrane elementy, są: {stala}fadeOut(){/stala}, {stala}slideDown(){/stala}, {stala}slideUp(){/stala}, {stala}fadeTo(){/stala}. Co więcej, można tworzyć własne, bardzo rozbudowane efekty. Służy do tego funkcja {stala}animate(){/stala}.