MooTools 1.2 - elementy strony cz. 3
28 września, 2008
W poprzednich częściach kursu nauczyliśmy się poruszać po drzewie dokumentu, tworzyć nowe elementy strony oraz zmieniać ich cechy, odczytywać je oraz przechowywać dodatkowe informacje w elementach. Przyszła pora poznać kilka metod dokonujących znaczących zmian w strukturze dokumentu - dwie z nich poznaliśmy wcześniej - adopt i clone, teraz nauczymy się kilku nowych.
Czy jesteś paragrafem ?
Wiemy, że typ elementu można sprawdzić za pomocą zapisu:
element.get('tag');
Gdybyśmy jednak potrzebowali sprawdzić czy dany element jest określonego typu (przykładowo paragrafem) to zamiast pisać:
if(element.get('tag') == 'p'){ // kod wykonywany po spełnieniu warunku }
Możemy skorzystać z metody match, która przyjmuje jako argument typ elementu i zwraca wartość true, jeżeli dany element jest właśnie takiego typu:
if(element.match('p')){ // kod wykonywany po spełnieniu warunku }
Przy okazji zapis warunku jest trochę krótszy.
Zmiany zawartości elementu
Wcześniej poznaliśmy też właściwości text i html, które pozwalały manipulować zawartością elementu. Aby wyczyścić element z wszelkich elementów i teksów należało zapisać:
element.set('html','');
Ale warto wiedzieć, że można to zapisać krócej za pomocą metody empty, która robi to samo co poprzedni zapis:
element.empty();
Możemy też dodawać do elementu tekst (i wokół niego) nie tylko za pomocą zapisu:
element.set('text', element.get('text')+'Nowy tekst');
ale także za pomocą o wiele prostszego zapisu z użyciem metody appendText o następującej składni:
element.appendText('tekstDoDodania', 'pozycja');
Parametr pozycja jest opcjonalny i przyjmuje jedną z czterech wartości: top, bottom, before, after. Wartość bottom jest wartością domyślną.
Najlepiej umiejscowienie tekstu po użyciu tych parametrów zademonstruje poniższy schematyczny kod:
// BEFORE <div id="test"> // TOP <p>Jakiś tekst</p> // BOTTOM </div> // AFTER
Po wywołaniu metody appendText:
$('test').appendText('Testowy tekst', pozycja);
Ze zmienną pozycja mającą jedną ze wspomnianych wcześniej wartości tekst zostanie dodany w miejsce odpowiedniego komentarza.
Z elementami jest podobnie
Metoda inject działa podobnie jak metoda appendText z tą różnicą, że operuje na całych elementach. Druga różnica jest taka, że pierwszym argumentem tej metody jest punkt odniesienia dla pozycji, zatem zapis:
element1.inject(element2, 'top');
Spowoduje umieszczenie element1 na samym początku element2. Na bazie tej metody i kilku wcześniej poznanych można zbudować całkiem szybko listę sortowalnych elementów.
Przyjmijmy, że mamy listę nieuporządkowaną, która zawiera kilka pozycji z różnymi tekstami. Każda z tych pozycji jest wyposażona w przyciski 'przesuń w górę' i 'przesuń w dół' - oczywiście krańcowe elementy są pozbawione jednego przycisku (jest on ukrywany w sposób dynamiczny). Niech nasza lista posiada atrybut id o wartości "dynamicList".
Każda pozycja listy będzie miała następującą budowę:
<li> Tekst <img src="up.png" alt="Przesuń w górę" /> <img src="down.png" alt="Przesuń w dół" /> </li>
Do przemieszczania elementów wystarczy poniższy kod:
window.addEvent("domready", function(){ $('dynamicList').getChildren().each(function(el){ el.getFirst('img').addEvent("click", function(){ el.inject(el.getPrevious(), 'before'); }); el.getLast('img').addEvent("click", function(){ el.inject(el.getNext(), 'after'); }); }); });
Dla każdego elementu listy dokonujemy selekcji obu przycisków i dodajemy do nich zdarzenia zawierające metody inject. Dla przycisku "Przesuń w górę" wykonujemy kod dokonujący wstawienia danego elementu przed poprzednim elementem, w wypadku drugiego przycisku wstawiamy element po następującym po nim elemencie.
Małą wada jest fakt, że krańcowe elementy nie mają ukrytych przycisków. Oczywiście można by ukrywać przycisk przy kliknięciu elementu w przesuwanych elementach i pokazywać potrzebne przyciski, które były ukryte, ale o wiele łatwiej jest stworzyć funkcję, która ukrywa pierwszy i ostatni przycisk w obrębie całej listy:
function hideButtons(){ $('dynamicList').getFirst().getFirst('img').setProperty('style','visibility:hidden'); $('dynamicList').getLast().getLast('img').setProperty('style','visibility:hidden'); }
Należy jeszcze uwzględnić fakt, że pewne przyciski trzeba ponownie pokazać użytkownikowi - zamiast pokazywać profilaktycznie wszystkie przyciski wystarczy dodać naszej funkcji jeden argument - element w którym należy ponownie pokazać przyciski:
function hideButtons(el1, el2){ if($defined(el1)){ el1.getElements('img').setProperty('style','visibility:visible'); el2.getElements('img').setProperty('style','visibility:visible'); } $('dynamicList').getFirst().getFirst('img').setProperty('style','visibility:hidden'); $('dynamicList').getLast().getLast('img').setProperty('style','visibility:hidden'); }
Warunek w pierwszej linijce funkcji jest potrzebny ponieważ musimy pamiętać, że trzeba dodatkowo ukryć przyciski przy inicjalizacji skryptu. Ostatecznie kod skryptu w całości wygląda następująco:
window.addEvent("domready", function(){ $('dynamicList').getChildren().each(function(el){ el.getFirst('img').addEvent("click", function(){ el.inject(el.getPrevious(), 'before'); hideButtons(el.getNext(), el); }); el.getLast('img').addEvent("click", function(){ el.inject(el.getNext(), 'after'); hideButtons(el.getPrevious(), el); }); }); hideButtons(); }); function hideButtons(el1, el2){ if($defined(el1)){ el1.getElements('img').setProperty('style','visibility:visible'); el2.getElements('img').setProperty('style','visibility:visible'); } $('dynamicList').getFirst().getFirst('img').setProperty('style','visibility:hidden'); $('dynamicList').getLast().getLast('img').setProperty('style','visibility:hidden'); }
Cały skrypt w akcji:
Usuwanie elementów
W jednej z poprzednich części kursu poznaliśmy metodę dispose, która pozwalała usunąć element z drzewa dokumentu. Istnieją jeszcze dwie inne metody, które pozwalają usuwać elementy - destroy i replaces. Metoda destroy różni się od metody dispose tym, że nie zwraca niczego, natomiast metoda dispose zwracała nam usuwany z drzewa dokumentu element, który mogliśmy ponownie wstawić do dokumentu, na przykład za pomocą metody inject. Z kolei metoda replaces usuwa dany element i zastępuje go innym :
nowyElement.replaces(staryElement);
Przy czym usuwanie w tej metodzie nie działa na zasadzie metody destroy:
staryElement.destroy();
Ale na zasadzie metody dispose - zatem zastępowany element możemy ponownie wstawić do dokumentu.
Wzbogacimy naszą listę o możliwość usuwania elementów - dodamy do struktury pozycji listy dodatkowy przycisk:
<li> Tekst <img src="up.png" alt="Przesuń w górę" /> <img src="delete.png" alt="Usuń ten element" /> <img src="down.png" alt="Przesuń w dół" /> </li>
Do jego obsługi wystarczy dodać poniższy kod w pętli dodającej zdarzenia do przycisków:
el.getChildren('img')[1].addEvent("click", function(){ el.destroy(); hideButtons(); });
Zatem cały kod prezentuje się teraz następująco:
window.addEvent("domready", function(){ $('dynamicList').getChildren().each(function(el){ el.getFirst('img').addEvent("click", function(){ el.inject(el.getPrevious(), 'before'); hideButtons(el.getNext(), el); }); el.getLast('img').addEvent("click", function(){ el.inject(el.getNext(), 'after'); hideButtons(el.getPrevious(), el); }); el.getChildren('img')[1].addEvent("click", function(){ el.destroy(); hideButtons(); }); }); hideButtons(); }); function hideButtons(el1, el2){ if($defined(el1)){ el1.getElements('img').setProperty('style','visibility:visible'); el2.getElements('img').setProperty('style','visibility:visible'); } $('dynamicList').getFirst().getFirst('img').setProperty('style','visibility:hidden'); $('dynamicList').getLast().getLast('img').setProperty('style','visibility:hidden'); }
Przykład po zmianach w akcji:
Otaczanie elementów
Na koniec opiszę dwie metody - grab i wraps. Metoda grab to odpowiednik metody adopt, który akceptuje tylko jeden element. Opcjonalnie możemy określić pozycję dodawanego elementu - top lub bottom:
rodzic.grab(potomek);
W poniższym wypadku element potomny zostanie umieszczony na samym początku elementu-rodzica:
rodzic.grab(potomek, 'top');
W tym wypadku element potomny zostanie umieszczony jako ostatni element potomny elementu-rodzica:
rodzic.grab(potomek, 'bottom');
Różnica pomiędzy działaniem metod grab i wraps jest dość subtelna, ale czasem może okazać się istotna - chodzi mianowicie o strukturę dokumentu po wykonaniu operacji.
Weźmy teraz pod uwagę następującą strukturę dokumentu:
<div id="test1">Test 1</div> <div id="test2">Test 2</div> <div id="test3">Test 3</div> <div id="test4">Test 4</div> <div id="test5">Test 5</div>
Jeżeli wykonamy operację:
$('test4').grab('test2');
Otrzymamy rezultat postaci:
<div id="test1">Test 1</div> <div id="test3">Test 3</div> <div id="test4">Test 4 <div id="test2">Test 2</div> </div> <div id="test5">Test 5</div>
Gdybyśmy teraz wykonali to samo, ale z użyciem metody wraps na początkowo wspomnianej strukturze:
$('test4').wraps('test2');
To otrzymamy:
<div id="test1">Test 1</div> <div id="test4">Test 4 <div id="test2">Test 2</div> </div> <div id="test3">Test 3</div> <div id="test5">Test 5</div>
Jak widać różnica pomiędzy tymi metodami polega na tym, że metoda wraps "owija" element rodzica wokół potomka, a metoda grab umieszcza potomka w elemencie rodzica. W rezultacie otrzymujemy dwa zupełnie inne rezultaty na stronie.
Dla treningu
Tym razem ciekawsze zadanie - proponuję ulepszyć naszą implementację listy tak by była ona wielopoziomowa - każdy z jej elementów może stać się elementem nadrzędnym osobnej listy. Aby uzyskać taki efekt warto zastanowić się nad użyciem metod grab i adopt. Zasada jest taka, że każdy element posiada dodatkowy przycisk do tworzenia podlisty (tworzenie podlisty polega na stworzeniu w danym elemencie kolejnej listy nieuporządkowanej tak by można się było do niej potem łatwo odwołać - tutaj można wykorzystać selektory lub metody set i get do przechowywania stosownych informacji). Dodatkowo pierwszy i ostatni element listy posiadałyby specjalne przyciski, które pozwalają umieścić je poziom wyżej z tym, że pierwszy element umieszczany by był przed listą z której pochodzi, a ostatni - za nią. Oczywiście należy pamiętać o ukrywaniu stosownych przycisków w określonym momencie - na przykład w momencie gdy dany element nie jest już pierwszym lub ostatnim elementem danej listy.
Podsumowanie
Poznaliśmy metody związane z manipulacją strukturą dokumentu i pozostało nam jeszcze zapoznać się z kilkoma metodami związanymi z klasami elementu oraz kilka metod, których nie można zaklasyfikować do jakiejś szerszej grupy funkcjonalności - to wszystko w kolejnej i ostatniej części kursu poświęconej zagadnieniom związanym z plikiem Element.js
Komentarze do wpisu "MooTools 1.2 - elementy strony cz. 3":
Jeszcze nie ma żadnych komentarzy. Twój może być pierwszy.
Dodaj komentarz: