metaxy quod erat demonstrandum…

28paź/091

Mootools odc. 3: Core

Odcinek trzeci kursu mootools i jednocześnie pierwszy stricte praktyczny. Części teoretycznej oczywiście też nie zabraknie, ale po raz pierwszy będzie można zobaczyć co to narzędzie potrafi w akcji. Nadszedł czas, aby zaznajomić się z rdzeniem frameworka.

Wprowadzenie

Core to element bazowy - jest niezbędny do działania całej reszty modułów. Oferuje on nam 15 funkcji - funkcji nie metod ponieważ nie są powiązane z żadnym obiektem. Są to:

Mamy już pełną listę dostępnych funkcji, więc rozpoczynamy omawianie każdej z nich.

boolean $chk(item)

Sprawdza, czy dana zmienna jest zdefiniowana lub przyjęła wartość 0 - wtedy zwraca nam true. Najczęściej wykorzystuje się ją w funkcjach, aby sprawdzić, czy został przekazany nam dany parametr. Jeżeli jako testowany argument zostanie przekazane: false, null, "" (pusty łańcuch znaków) lub undefined otrzymamy false. Może służyć do obsługi opcjonalnych argumentów.
function add(one, two, three, four) {
var ret = one + two + three;
if ($chk(four)) ret += four;
return ret;
}
add(1, 2, 3); // 6
add(1, 2, 3, 5); // 11
add(1, 2, 3, 0); // 6
Gdybyśmy jednak nie użyli funkcji $chk i a naszą zapisali:
function add(one, two, three, four) {
var ret = one + two + three + four;
return ret;
}
add(1, 2, 3, 5); // 11
add(1, 2, 3); // NaN
Drugie wywołanie zwróciłoby NaN - Not a Number. Stałoby się tak ponieważ do 6 (1 + 2 + 3) dodalibyśmy undefined co nie może być poprawną operacją matematyczną. Jeżeli chodzi o przekazywanie obiektów do funkcji to samo $chk to zbyt mało, ale o tym za chwilę.

void $clear(timer)

Jedna z rzadziej używanych funkcji. Pozwala na usuwanie timerów. Timery to funkcje, które są wykonywane po określonym czasie (setTimeout) lub co określony czas (setInterval). Tworzenie timerów odbywa się poprzez 2 metody obiektu Function: delay i periodical lub wcześniej wspomniane natywne funkcje JavaScriptu. Malutki przykład (kto, komu i za co płaci zostawiam Waszej fantazji):
var count = 0;
var pay = function () {
if (++count > 3) {
$clear(pay);
alert('Dość się już napłaciłem');
} else
alert('Zapłaciłem');
}.periodical('2000');
Zastosowanie? Np. przy okresowym pobieraniu jakichś danych z XHTTPRequest (popularne i błędnie określane mianem AJAXa).

boolean $defined(object)

Funkcja o niemal identycznym działaniu jak $chk. Jedyną różnicą jest to, że sprawdza, czy dana zmienna została zainicjalizowana (ustawiona), czyli nie jest undefined bądź null. Zupełnie jak isset w PHP. Jeżeli wartość została ustawiona zwraca true. Oczywiście literały (bezpośrednio wpisane wartości) zwracają prawdę;
var arg = $arguments(2);
$defined(arg); // true
$defined(1); // true
function fun(arg1, arg2) {
return $defined(arg1);
}
fun(); // false
fun(1); // true
fun(null, 2); // false
fun(false); // true
$defined(foo); // błąd

function $arguments(i)

Sposób działania tej funkcji może wydać się sporej części z Was dziwna, aczkolwiek jest to dosyć częsta praktyka w JavaScript. Zwracaną wartością jest funkcja. O ile sama praktyka zwracania funkcji bądź podstawiania ją pod zmienną jest nierzadko spotykana to samo wykorzystanie $arguments już nie. Mnie prawdę mówiąc nigdy się to nie zdarzyło (wolę używać arguments[i]), więc przykład też tylko tutorialowy:
var arg = $arguments(2);
arg(3, 5, 9);
Jeżeli ktoś tego używa i poda sensowne wytłumaczenie czemu to będę wdzięczny, reszta może praktycznie o tym zapomnieć.

function $empty

Tworzy pustą funkcję - ot zagadka po co komuś pusta funkcja. Najczęściej wykorzystuje się ją jako pojemnik (placeholder) na metody w klasach. Zdaję sobie sprawę, że na razie to wysoki poziom abstrakcji - dojdziemy do klas wszystko stanie się łatwiejsze. $empty jest równoznaczne z zapisem funkcji pustej bez parametrów, czyli:
function() {}
$empty; // równoznaczny zapis

function $lambda(value)

Rzecz podobna do $empty - również tworzy funkcję z tą jednak różnicą, że zwraca ona podaną przez nas wartość. Poniżej dwa równoznaczne zapisy:
function() {
return 1;
}
$lambda(1); // równoznaczny zapis
Do czego może się nam to przydać? Znów do klas lub miejsc, gdzie wymagana jest funkcja, a nie konkretna wartość. Funkcja to recepta na wykonanie czegoś. Ktoś tworząc klasę starał się zrobić ją uniwersalnie, więc mamy możliwość podania funkcji, która po skomplikowanych obliczeniach zwróci jakąś wartość. Jednak dla innej osoby wystarczy, że poda gotowy wynik (jak np. nasze 1 z przykładu) - więc zapis z lambdą jest po prostu wygodniejszy. Prosty przykład:function() {
return 1;
}
$lambda(1); // równoznaczny zapis

object $extend(original, extension)

Łączy ze sobą dwa obiekty. Do pierwszego zostają przepisane własności drugiego. Jeżeli klucze powtarzają się w obu obiektach zostają nadpisane przez te pochodzące z drugiego. Na żywo:
var maluch = {
ovner: 'Jan Kowalski',
color: 'czerwony',
abs: 'tak'
}
var porsche = {
ovner: 'Mirek Nowak',
color: 'żółty',
radio: 'nie'
}
var afterCrash = $extend(maluch, porsche);
/* afterCrash = {
ovner: 'Mirek Nowak',
color: 'żółty',
abs: 'tak',
radio: 'nie'
} */
Wynik zaskakujący po połączeniu (zderzeniu) nie otrzymaliśmy pomarańczowego kawałka złomu.

object $merge(obj1, obj2[, obj3[,...]])

Łączy ze sobą dwa obiekty. Do pierwszego zostają przepisane własności drugiego. Jeżeli klucze powtarzają się w obu obiektach zostają nadpisane przez te pochodzące z drugiego. Na żywo:
var blonde = {
IQ: 60,
height: 178,
pets: {
dog: 'Misiek',
cat: 'Bobik'
}
}
var redhead = {
IQ: 110,
height: 170,
pets: {
dog: 'Reksio',
alligator: 'Pusia'
}
}
var brunette = {
IQ: 140,
height: 162
}
var mix = $merge(blonde, redhead, brunette);
/* mix = {
IQ: 140,
height: 162,
pets: {
dog: 'Misiek',
cat: 'Bobik',
alligator: 'Pusia'
}
}
*/
W wyniku połączenia blondynki z rudą i brunetką otrzymaliśmy kobietę mądrą, choć niewysoką i całą menażerią. Jaka jest więc różnica między $extend, a $merge? Są dwie: $merge potrafi łączyć dowolnie wiele obiektów ze sobą oraz potrafi łączyć zagnieżdżone obiekty w obiektach (w naszym przykładzie zwierzaki). $merge może zawsze zastąpić $extend, odwrotnie już tak nie jest.

void $each(iterable, fn[, bind])

Kolejne odniesienie do PHP - wypisz wymaluj instrukcja foreach. Delikatnie tylko inna składnia aczkolwiek działanie to samo. Pierwszym parametrem jest tablica/obiekt, który chcemy przejść, drugim funkcja anonimowa (bo nie ma ona nazwy), która definiuje co chcemy zrobić:
$each(['pies','kot','rybka'], function(pet, index) {
console.log(index + '. ' + pet);
});
// wynik: "0. pies", "1.kot", "2.rybka"
Parametry podstawianej funkcji anonimowej (oczywiście kolejność jest istotna i co więcej wskazuje częstość ich użycia - pierwszy zawsze, drugi rzadziej, trzeci mało kiedy):

  1. wartość
  2. indeks (numerowany od zera) dla tablic bądź klucz dla obiektów
  3. tablica bądź obiekt, który obecnie przetwarzamy

To samo możemy zastosować do obiektów (znów osoby ze znajomości PHP skojarzą tablice asocjacyjne):
var family = {
'mother': 'Anna',
'father': 'Jan',
'brother': ['Tomasz', 'Michał', 'Grzegorz'],
'sister': 'Monika'
}
$each(family, function(name, key) {
console.log(key + ' - ' + name);
});
// wynik: "mother - Anna", "father - Jan", "brother - Tomasz,Michał,Grzegorz", "sister - Monika"

W praktyce jednak częściej zapewne będziecie używać metody each obiektów Hash i Array.

mixed $pick(var1[, var2[, var3[, ...]]])

Zwraca pierwszy argument, który nie jest równy null lubnull właśnie jeżeli, każdy z argumentów jest null:
function test(a, b, c) {
return $pick(a, b, c);
}
test('jeden', 'dwa', 'trzy'); // jeden
test(false, true); // false
test(null, 'alfa', 'beta'); // alfa
test(); // null
test(null, null, null); // null
test(null, 'tekst', null); // tekst
test(null, null, 'kot'); // kot
test(a, null, 'kot'); // bład bo a nie zostało nigdzie zdefiniowane

number $random(min, max)

Losowa liczba z zakresu (przedział obustronnie domknięte, czyli włącznie np. <4, 6> może wylosować 4, 5 lub 6). Funkcja szczególnie lubiana przez wykładowców na studiach:
alert("Pan, drogi studencie zaliczył dziś na: " + $random(2, 5));

array $splat(obj)

Zamienia każdy przekazany obiekt na jednoelementową tablicę chyba, że przekazano tablicę - wtedy zwraca tą samą nieprzetworzoną tablicę. Należy zwrócić uwagę, że funkcja ta nie konwertuje obiektów (object) na tablice, a po prostu wstawia go jako pierwszy element nowej tablicy.
var obj = {
cat: 'Miki',
dog: 'Rom'
}
$splat(obj); // [{cat: 'Miki', dog: 'Rom'}]
$splat(false); // [false]
$splat(1); // [1]
$splat([1, 5, 6]); // [1, 5, 6]

number $time()

Zwraca uniksowy znacznik czasu (timestamp):
$time(); // 1256758382146

mixed $try(fn[, fn, fn, fn, ...])

Funkcja próbuje wykonać funkcje przekazane jej jako parametry i zwraca wartość, którą jej zwróciła pierwsza funkcja, która została wykonana prawidłowo. Jeżeli żadna nie zostanie wykonana bezbłędnie zwraca null:
var fun1 = function () {
return 0;
}
var fun2 = function () {
return 2 / 0; // dzielenie przez zero nie jest błędem w rozumieniu funkcji $try
}
var fun3 = function () {
return a; // nie ma takiej zmiennej jak a
}
var fun4 = function () {
return Array.xyz(); // nie ma takiej metody jak xyz()
}
$try(fun1, fun2, fun3, fun4); // 0
$try(fun3, fun4); // null
$try(fun2, fun4); // Infinity

mixed $type(object)

Funkcja testuje czym jest przekazany jej argument (niczym wycofywane z PHP, a przynajmniej niezalecane, gettype). Może zwrócić string opisujący słownie, czym jest argument bądź false jeżeli jest wartością niesprecyzowaną (szczegóły poniżej):

  • element - element drzewa DOM
  • textnode - węzeł tekstowy DOM
  • whitespace - węzeł tekstowy DOM, w którym są wyłącznie białe znaki (spacja, nowa linia, tabulacja, etc.)
  • arguments - argumenty funkcji
  • array - tablica
  • object - obiekt
  • string - łańcuch znaków
  • number - liczba
  • date - data
  • boolean - wartość logiczna (true lub false)
  • function - funkcja
  • regexp - wyrażenie regularne
  • class - klasa stworzona przez new Class bądź rozszerzenie innej klasy
  • collection - kolekcja elementów DOM (np. zwrócone przez metody klasy Elements bądź natywne funkcje jak np. getElementByTagName)
  • window - obiekt window
  • document - obiekt document
  • false - jeżeli testowana wartość jest undefined, null, NaN lub też żadną z powyższych

Przykłady użycia:
var str = "tekst";
$type(str); // string
$type(document.getElementById('menu')); // element
Gdzie tak naprawdę się ich używa? Np. do testowania przekazanych parametrów dla funkcji co pozwala w dosyć okrężny sposób stosować przeciążanie funkcji.
function test(arg1) {
switch ($type(arg1)) {
case 'string': return 'Przekazano: ' + arg1; break;
case 'number': return Math.pow(arg1, 2); break;
default: alert('Błędny parametr');
}
}
test("kot"); // Przekazano: kot
test(2); // 4 - bo 2 do potęgi 2
test(false); // alert z komunikatem "Błędny parametr"

Podsumowanie

Możemy przyjąć, że na pewno połowę z tych funkcji będziecie stosować całkiem często. Macie już pewne podstawy do startowania z mootools, ale wierzcie mi lub nie - fura nauki jeszcze przed Wami. Cóż - nikt nie obiecywał, że nie będzie bolało.
Pytania, poprawki, błędy, uwagi? Ktoś mądry po to właśnie wymyślił komentarze, więc droga wolna.
PS. W tym tygodniu miały być dwie rzeczy Core i Browser. Wyszło samo Core bo jak widzicie wpis i tak zrobił się długi. Browser podepniemy pod jakąś mniejszą objętościowo notkę.

W następnym tygodniu w “MooTools”

Tablice, czyli klasa Array - spora i naprawdę potrzebna rzecz.

Komentarze (1) Trackbacks (0)
  1. Zaczyna się robić ciekawie! Dzięki! :D


Dodaj komentarz


Spam Protection by WP-SpamFree

Brak trackbacków.