Kurs: Framework Prototype JS w pigułce. Cz. 1.

Prototype JS

Poziom średnio-zaawansowany

Oto pierwsza część krótkich kursów, opisująca bliżej frameworki JavaScript. Pierwszym z nich będzie Prototype JS.

Framework Prototype JS – od podstaw

Garść wstępnych informacji opisujących Framework Prototype JS, pojawiła się już w artykule Frameworki JS – słowo wstępne.

Celem niniejszego artykułu nie jest zastąpienie dokumentacji, ale opis kluczowych elementów biblioteki, który wystarczy programiście do zrozumienia zasad i pozwoli swobodnie programować.

Może także stanowić „ściągawkę” dla już obeznanych z tym frameworkiem.

Do dzieła! Pobieramy bibliotekę, dodajemy do strony i już możemy z jej dobrodziejstw.

Tip: możemy także szybko dołączyć framework Prototype JS z CDN:

<script src="//ajax.googleapis.com/ajax/libs/prototype/1.7.1.0/prototype.js"></script>

Używając następującego kodu, sprawdzimy czy Prototype JS został załadowany:

if (typeof Prototype === "undefined") {
    throw new Error("Ten skrypt wymaga Prototype JS");
}

// tudzież po prostu 
//if (typeof Prototype != "undefined") {
  // kod ...
//}

Przejdźmy dalej.

Obiekt Element

Na początku powiemy o obiekcie Element, umożliwiającym operacje na elementach dokumentu.

Przykład – sprawdzanie, czy element jest widoczny:

function isHidden(item_name) {
    if ($(item_name).style.display == "none")
        return true;
    else return false;
}

alert(isHidden('foobar');

Element można ukryć / schować wygodnie, zamiast style.display używając metod show() i hide():

$('element_id').hide();

Funkcja update – aktualizacja elementu:

<div id="topSecret" style="display: none;">Niewidoczny</div>
// ...
$('topSecret').update('Widoczny').show();

Jak widać, wywołania metod można w prosty sposób ze sobą łączyć.

Funkcje narzędziowe Prototype JS

Pora na magię framework’ów, czyli specjalne funkcje narzędziowe.

Funkcja $() – obudowana wersja getElementById(), można podać ID elementu jak i przekazać sam element, i odwoływać się do niego.

Funkcję $() spotkamy nie tylko we framework’u Prototype JS – jest często spotykana w innych rozwiązaniach tego typu.

Przykład – użycie funkcji $():

// ukryj wybrane elementy:
$('item1', 'item2', 'item3').invoke('hide');

Możemy podać zarówno jeden jak i kilka nazw (ID) elementów. Metoda invoke() z obiektu Enumerable natomiast, służy do wywołania danej akcji dla wszystkich podanych elementów.

Funkcja $$() – podwójne $$ – pozwala wybierać elementy według klas CSS, odbywa się to w postaci:

$$('element');

Przykłady – użycie funkcji $$():

// wszystkie elementy typu div; to samo co użycie
// document.getElementsByTagName('div')
$$('div');

$$('#content'); // to samo co $('content'), zwraca tablicę

$$('li.foobar'); // pobiera wszystkie elementy LI z klasą foobar

Pseudo-elementy (od wersji 1.5.1+)

Czyli składnia rozszerzona, pozwalająca na dostęp do przeróżnych elementów, używając zwięzłej składni zamiast rozbudowanego kodu.

Przykłady – użycie pseudo-elementów:

Przykładowa struktura HTML:

<div id="content">
  <p id="par1">Dane testowe.</p>
  <a href="www.foobar.com">Link 1</a>
  <a href="www.foo1.com" rel="nofollow">Link 2</a>
  <a href="www.foo2.com" rel="start">Link 3</a>
  <a href="#" rel="start">Link 4</a>
</div>

Obsługa w JavaScript i Prototype JS:

// pobierz kolekcję linków będących wewnątrz elementu
// od id = "content", mających atrybut rel
$$('#content a[rel]');

// wszystkie linki, których atrybut href ma wartość "#"
$$('a[href="#"]');

// wszystkie linki (element a) wewnątrz elementu 
// z id = "navbar" lub "content"
$$('#navbar a', '#sidebar a');

Gdy się temu przyjrzymy dostrzeżemy możliwości jakie dostajemy, oraz oszczędność czasu, wystarczy tylko opanować używanie tego typu składni.

Przykłady zaawansowane:

// pobierz tylko pola tekstowe
$('input[type="text"]')

// wszystkie linki, oprócz (~=) tych zawierających 
// "nofollow" w atrybucie rel
$$('a:not([rel~=nofollow])');

// wszystkie parzyste wiersze w tabelach
$$('table tbody > tr:nth-child(even)');

// puste elementy div (bez tesktu, tylko białe znaki, itp)
$$('div:empty');

// pobieranie względem położenia

// wszystkie dzieci elementu ul z id = menu
$$('ul#menu > li')

// negacja
$$('ul#menu li:not(.current)')

// elementy nie posiadające atrybutu rel
$$('ul#menu a:not([rel])')

Pseudo-elementy to naprawdę świetne narzędzie.

Wróćmy teraz do dalszego poznawania funkcji narzędziowych.

Funkcja $F()

Służy ona do odczytywania wartości elementu formularza, jak input, select, itd.

Przykład – prosta obsługa formularza:

// w prosty sposób odczytamy wartość listy
var value = $F( "lista_testowa_id" );

Funkcja $A()

Kopiuje lub konwertuje dowolną listę (jak childnodes), na obiekt typu Array, przez co umożliwia szybszy dostęp do poszczególnych elementów tablicy.

Przykład – użycie funkcji $A():

function showOptions() {
    var someNodeList = $('lstEmployees').
        getElementsByTagName('option');

    var nodes = $A(someNodeList);

    nodes.each(function(node) {
        alert(node.nodeName + ': ' + node.innerHTML);
    });
}

Otrzymujemy kolekcję z danymi pobranymi z elementu HTML (np. pola typu Select). Kolejny przykład tworzy kolekcję zawierającą paragrafy (elementy <p>) dokumentu.

Przykład #2:

var paras = $A(document.getElementsByTagName('p'));
paras.each(Element.hide);
$(paras.last()).show();

Jeszcze bardziej interesująca może być kolejna funkcja.

Funkcja $H()

Przekształca argument na hash implementujący tablicę asocjacyjną, np.:

var testowyObiekt = { width: 100, height: 100, depth: 20 };
var testowyHash = $H( testowyObiekt );
var wynik = testowyHash.toQueryString();
alert(wynik);

Kolekcje danych i Enumerable

Znów mała przerwa w omawianiu funkcji narzędziowych.

Kolekcje danych – w Prototype JS korzystamy z faktu, że dziedziczą one z Enumerable, więc możemy użyć przetwarzania dedykowanego.

Przykładem jest each:

$( "a1", "b2", "c" ).each(function(item, index) {
    alert(item + " znajduje się pod indeksem " + index);
    item.style.width = 180;
});

Jak widać otrzymujemy przyjemny w użyciu iterator.

Idźmy dalej.

Funkcja $R()

Funkcja ta daje programiście zwięzły sposób zapisu instrukcji new (argumenty: lowerBound, upperBound, excludeBounds), która reprezentuje zakres wartości ograniczony argumentami dolnej i górnej granicy, dla tworzonej tablicy:

var zasieg = $R(20, 100, false);
zasieg.each(function(value, index) {
    alert("Wynik dzialania" + value);
}); 

$A($R('aa', 'ah')).join(', '); // aa, ab, ac, ad, ae, af, ag, ah
$R(0, 10, true).include(10) // false

$R(0, 10, true).each(function(value) {
    // invoked 10 times for value = 0 to 9
});

Funkcja $w()

Przekształca string w tablice, jak qw(foo bar) w języku Perl:
$w(String) -> Array

Przykład – użycie funkcji $W():

$w('apples bananas kiwis') // ['apples', 'bananas', 'kiwis']

$w('ads navbar funkyLinks').each(Element.hide); // ukryj te elementy

Pora na coś specjalnego.

Funkcja Try.these()

Pomaga nam przy różnicach w implementacji dla przeglądarek (szuka najlepszego wariantu).

Przykład – użycie funkcji Try.these() – crossbrowser support:

createXMLHttp: function() {
    return Try.these(
        function() { return new XMLHttpRequest() },
        function() { return new ActiveXObject('Msxml2.XMLHTTP') },
        function() { return new ActiveXObject('Microsoft.XMLHTTP') }
    ) || false;
}

Events – obsługa zdarzeń

Framework Prototype JS daje nam wygodną obsługę zdarzeń. Jej podstawą jest obiekt Event.

Przykład – obsługa zdarzenia pojawienia się kursora myszy nad elementem o ID „foobar”:

Event.observe('foobar', 'mouseover', function() {
    alert('Mysz!');
});

Można powiedzieć, że zarejestrowaliśmy tutaj obserwator (observer) reagujący w dany sposób na określone zdarzenie (event) dla danego elementu.

Kolejny przykład to obsługa zdarzenia wczytania dokumentu (strony):

Event.observe(window, 'load', function() {
    // ...
});

AJAX i Framework Prototype JS

Prototype JS jest znakomitym frameworkiem również jeśli chodzi o wspieranie pracy z Ajax. Izoluje poziom implementacji od konkretnej przeglądarki, dając nam do ręki wygodne narzędzia pracy z Ajax.

Ajax.Updater – czyli wywołanie Ajax z odświeżeniem elementu strony.

Posiada dodatkowe opcje:

– evalScripts (default false)

– insertion (‚top’, ‚bottom’, ‚before’, ‚after’)

Przykład – Ajax.Updater():

new Ajax.Updater('items', '/items', {
    parameters: { text: $F('text') },
    insertion: Insertion.Bottom
});

Przykład 2:

function _updateX(tmp_id) {
    new Ajax.Updater('id2', '/module/action, {
        asynchronous: true,
        evalScripts: true,
        parameters:{
            id: tmp_id
         }
    });
}

Drugi argument (module / action) to adres do zasobu po stronie serwera, który odbierze (żądanie) request.

Zdefiniowanie zdarzeń success oraz failure:

function testAjax() {
  new Ajax.Updater({ success: 'newsContent', failure: 'errors' },
    '/prototypejs/data', { 
      method: 'post', insertion: Insertion.Top 
  });
}

Ajax.Request – to kolejne, podobne do Updater() narzędzie; użyjemy do szczególnie tam, gdzie nie koniecznie chcemy zaktualizować element strony.

Przykład – użycie Ajax.Updater():

// plik ajax.js
alert('witaj!');

// wywołanie
new Ajax.Request('my_ajax.js', { method: 'get' });

Przykład #2:

function testAjax() {
    new Ajax.Request('/prototypejs/data', {
        method: 'get',
        onSuccess: function(transport) {
            $('news').innerHTML = transport.
                responseText || "brak danych";
        },
        onFailure: function() {
            alert('Wystąpił błąd podczas pobierania danych')
        }
    });
}

Dostęp do JSON

W opisywanym ostatnio artykule o JSON pisaliśmy o podstawowej obsłudze formatu JSON w JavaScript. Framework Prototype JS daje nam swoje sposoby w zestawie.

Przykład – framework Prototype JS i użycie JSON:

new Ajax.Request('/some_url', {
    method: 'get',
    requestHeaders: { Accept: 'application/json' },
    onSuccess: function(transport) {
        var json = transport.responseText.evalJSON(true);
    }
});

Zdefiniowaliśmy tu nowy rodzaj parametru: requestHeaders. Odnosi się on do nagłówka żądania, a w naszym przykładzie określa typ akceptowalnych danych (JSON).

Przekazanie parametrów możemy wykonać w następujący sposób:

function testAjax() {
    var url = "/prototypejs/data";
    var params = new Object();

    params.method = "get";
    params.parameters = "osoba = Jan";
    params.onComplete = putText;
    params.onFailure = showErrorMsg;

    new Ajax.Request(url, params);
}

Jeśli chcemy przekazać parametry, używamy właściwości postBody.

Przykład – przekazanie argumentów żądania poprzez postBody:

new Ajax.Request('/foo/bar', { 
    method: 'post', 
    postBody: 'thisvar=123&thatvar=Xyz' 
});

Natomiast evalScripts ustawiona na true, wykona skrypty blokach <script> </script>

Przykład – nakazanie wykonania kodu JS:

newAjax.Updater('mydiv', '/foo/bar', { 
    asynchronous: true,
    evalScripts: true 
});

Periodyczna aktualizacja fragmentu strony – PeriodicalUpdater.

Jest to ciekawe i przydatne rozwiązanie od twórców Prototype JS. Dzięki niemu możemy nakazać wykonywanie żądania Ajax co określony czas (wszystko łatwo definiowalne poprzez parametry).

Przykład – zastosowanie Ajax.PeriodicalUpdater:

function testAjax() {
    new Ajax.PeriodicalUpdater('dyn_content', '/action/data', {
        // insertion: bottom, etc...
        method: 'get', frequency: 3, decay: 2
    });
}

A na koniec przykład definicji globalnych.

Przykład – użycie Ajax.Responders

// insertion: bottom, etc ...
Ajax.Responders.register({
    onCreate: showLoader,
    onComplete: hideLoader
});

Tym samym wykonaliśmy rejestrowanie funkcji do wszystkich wywołań AJAX.

Wspólne opcje Ajax (common options) – bardziej szczegółowy i aktualny opis dla nich znajdziemy w dokumentacji.

Podsumowanie

Dotarliśmy wreszcie do końca części I kursu traktującego o framework’u Prototype JS. Być może jest nieco dłuższa niż inne artykuły, ale w końcu poruszamy dość rozbudowany temat.

Zapraszam do kolejnych części i kolejnych kursów, które pojawią się wkrótce. Dziękuję za uwagę.

Programista WWW i aplikacji mobilnych z wieloletnim doświadczeniem, początkujący bloger. Pasjonat programowania, nowych technologii, e-commerce, a także sportu i motoryzacji.

Twitter LinkedIn Google+ Skype Xing 

Podaj dalej: Share on Facebook1Tweet about this on TwitterShare on Google+2Share on LinkedIn1Share on Tumblr0Digg thisEmail this to someonePin on Pinterest1
Możesz skomentować leave a response, lub podać trackback z własnej strony.
  • Adam P.

    Niezły art! Zakładam że to dopiero początek, i że pojawią się kursy / arty o innych bibliotekach, choćby jQuery, right?

    Pzdr!

  • Hey,

    zgadza się. Będą popularne frameworki, które różnią się budową i wachlarzem oferowanych możliwości.

    Każdy interesujący na swój sposób – jQuery, MooTools, YUI, dojo, itp…
    dla każdego coś dobrego – tylko odrobinę to potrwa 🙂