MooTools 1.2 - elementy strony cz. 2
05 września, 2008
W kolejnej części kursu poświęconej elementom strony, zajmiemy się dynamicznym tworzeniem elementów, zmienianiem ich atrybutów oraz zapoznamy się z zupełnie nową funkcjonalnością klasy Element - możliwością przechowywania informacji w obiektach tej klasy.
Tworzenie elementów
Prędzej czy później podczas tworzenia bardziej złożonego skryptu JavaScript zachodzi potrzeba stworzenia zupełnie nowego elementu "w locie". W MooTools wystarczy stworzyć nowy obiekt klasy Element z podanym jednym argumentem - typem elementu:
var nowyDiv = new Element('div');
Jest to najprostszy przykład użycia konstruktora elementów. Ma on jednak o wiele bardziej rozbudowane możliwości - możemy określić zawartość poszczególnych atrybutów danego elementu - dokonujemy tego dzięki obiektowi podanemu jaki drugi argument konstruktora:
var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy' });
Dodatkowo możemy określić styl elementu w obiekcie style:
var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' } });
Istnieją jeszcze trzy parametry do określenia - zawartość elementu możemy określić poprzez właściwości text lub html - różnica oczywiście polega na tym, że z pierwszej z nich korzystamy dodając tylko tekst, a z drugiej podczas dodawania tekstu z kodem (X)HTML:
var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' }, 'text': 'przykładowy tekst' });
var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' }, 'html': '<strong>przykładowy pogrubiony tekst</strong>' });
Ostatnia właściwość to events - pozwala od razu określić zdarzenia elementu:
var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' }, 'text': 'przykładowy tekst', 'events': { 'click': function(){ // kod zdarzenia onclick }, 'mouseenter': function(){ // kod zdarzenia onmouseenter }, 'mouseleave': function(){ // kod zdarzenia onmouseleave } } });
Jak widać można całkiem spory kawałek kodu wygenerować dla stworzenia pojedynczego elementu z zawartością i zdarzeniami.
Konstruowaniem nowych elementów zajmiemy się poważniej przy okazji następnej części poświęconej elementom strony i m.in. metodzie inject. Warto jednak zwrócić uwagę na pewne podobieństwo konstruktora elementu do metody set.
Set i get
Każdemu obiektowi klasy Element możemy określić wartości poszczególnych cech za pomocą metody set. Możemy to robić pojedynczo:
$('testowy').set('class','nowaKlasa');
Lub ustawiać kilka właściwości naraz podając jako argument tej metody obiekt podobny do obiektu będącego drugim argumentem konstruktora. Zatem zapis:
var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' }, 'text': 'przykładowy tekst', 'events': { 'click': function(){ // kod zdarzenia onclick }, 'mouseenter': function(){ // kod zdarzenia onmouseenter }, 'mouseleave': function(){ // kod zdarzenia onmouseleave } } });
moglibyśmy zapisać również jako:
var nowyDiv = new Element('div') nowyDiv.set({ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' }, 'text': 'przykładowy tekst', 'events': { 'click': function(){ // kod zdarzenia onclick }, 'mouseenter': function(){ // kod zdarzenia onmouseenter }, 'mouseleave': function(){ // kod zdarzenia onmouseleave } } });
Warto jeszcze wiedzieć, że w wypadku właściwości html i metody set, możemy jako argumenty podać kilka łańcuchów kodu (x)HTML:
$('testowy').set('html','<em>tekst</em>','<strong>tekst</strong>');
W powyższym wypadku zostaną dodane dwa teksty do elementu - kursywa i pogrubienie.
Gdybyśmy potrzebowali pobrać wartości poszczególnych właściwości wystarczy wykorzystać metodę get:
$('testowy').get('class');
Możemy też pobrać typ elementu:
$('testowy').get('tag');
Powyższy kod zwróci nam na przykład wartość 'div' jeżeli dany element jest divem.
Od razu uprzedzam, że zapis:
$('testowy').set('tag','strong');
Nie zamieni diva w pogrubienie - doda po prostu atrybut tag do tego elementu o wartości strong.
Warto jeszcze wiedzieć, że do czyszczenia danej właściwości służy metoda erase, która ma składnię podobną do metody get - pobiera nazwę właściwości do wyczyszczenia, zatem zapis:
$('testowy').erase('id');
Wyczyści atrybut id naszego elementu i uniemożliwi kolejne odwołania do niego poprzez selektor:
$('testowy')
Własne set, get i erase
MooTools udostępnia nam obiekt, który pozwala nam określić własne implementacje metod set, get oraz erase dla danej właściwości - Element.Properties.
Przykładowo dla właściwości html metoda set wygląda następująco:
Element.Properties.html = { set: function(){ return this.innerHTML = Array.flatten(arguments).join(''); } };
Jest to o tyle przydatna funkcjonalność, że możemy zmienić obsługę poszczególnych właściwości na wygodniejszą dla nas. Koncepcje wykorzystania pozostawiam Wam - kilka możecie znaleźć w kodzie źródłowym MooTools :)
Zawężamy zakres działań
Metody get, set i erase dają nam dostęp do wszystkich najważniejszych cech elementu - jego zdarzeń, stylu i atrybutów. Gdybyśmy jednak chcieli się ograniczyć tylko do atrybutów elementu to mamy do dyspozycji sześć metod będących odpowiednikami metod get, set i erase. Każda z tych metod ma swój odpowiednik podobnie jak $ i $$ czy getElement i getElements:
- getProperty,
- getProperties,
- setProperty,
- setProperties,
- removeProperty,
- removeProperties
Składnia tych metod nie jest skomplikowana - pobranie pojedynczego atrybutu wymaga zapisu:
$('testowy').getProperty('class');
Natomiast pobranie wartości kilku atrybutów naraz wymaga podania po prostu większej liczby argumentów:
$('testowy').getProperties('class', 'title');
Warto przy tym pamiętać, że getProperty zwraca po prostu wartość atrybutu, a getProperties zwraca obiekt postaci:
{ 'class' : 'nazwaKlasy', 'title' : 'tytulElementu' }
Metoda setProperty ma składnię podobną do metody getProperty:
$('testowy').setProperty('class', 'nazwaKlasy');
Natomiast metoda setProperties pobiera jako argument obiekt - na przykład taki jak ten zwracany przez metodę getProperties:
$('testowy').setProperties({ 'class' : 'nazwaKlasy', 'title' : 'tytulElementu' });
Jeżeli chodzi o metody removeProperty i removeProperties to składniowo przypominają metody getProperty i getProperties:
$('testowy').removeProperty('class'); $('testowy').removeProperties('class', 'title');
Kilka z tych metod wykorzystamy w przykładzie do tej części kursu.
Gdy potrzeba przechować coś więcej
Najciekawszą nowością w MooTools 1.2 jeżeli chodzi o właściwości elementów są metody store i retrieve. Ileż to razy przydałoby się przechować jakieś informacje o elemencie ? Wcześniej z reguły można było kombinować z tablicami asocjacyjnymi, ukrywaniem danych w dostępnych atrybutach elementu itd. A teraz wystarczy zapisać:
$('testowy').store('jakasCecha', 'jakasWartosc');
I już mamy przechowaną wartość w elemencie - możemy ją odczytać poprzez zapis:
$('testowy').retrieve('jakasCecha');
Dla przykładu stworzymy sobie prosty licznik kliknięć w wybrane elementy strony.
Niech wszystkie elementy dla których mają być zliczane kliknięcia mają jedną cechę wspólną - klasę storage. To na jej podstawie będziemy dokonywali selekcji tych elementów dla celów statystycznych oraz będziemy korzystać z tej cechy w obserwatorze zdarzenia onclick dotyczącym całego dokumentu. Informacje będzie przechowywała cecha o nazwie clickCounter.
Na początek zainicjalizujemy pierwszą wartość - zero dla naszej cechy we wszystkich elementach z klasą storage:
window.addEvent("domready", function(){ $$('.storage').each(function(el){ el.store('clickCounter', 0); }); });
Do tego musimy dodać stosowny obserwator zdarzenia onclick, który do każdego kliknięcia elementu klasy storage doda operację zwiększenia wartości clickCounter o jeden:
window.addEvent("domready", function(){ $$('.storage').each(function(el){ el.store('clickCounter', 0); }); document.body.addEvent("click", function(event){ var elmt = new Event(event).target; if(elmt.getProperty('class') == 'storage'){ var counter = elmt.retrieve('clickCounter'); counter++; elmt.store('clickCounter', counter); } }); });
Ostatnia ważna sprawa to prezentacja statystyk kliknięć. Ja proponuję by znalazły się one w divie z listą nieuporządkowaną, której pozycje będą prezentowały typ elementu i jego atrybut id oraz ilość kliknięć w postaci :
typ#idElementu - ilość Kliknięć
Dane będą aktualizowane za pomocą funkcji stats:
function stats(){ var statContent = ''; $$('.storage').each(function(el){ statContent += '<li>' + el.get('tag') + '#' + el.get('id') + ' - ' + el.retrieve('clickCounter') + '</li>'; }); $('stats').set('html', statContent); }
Oczywiście wywołanie tej funkcji umieszczamy w kodzie obserwatora zdarzenia onclick:
window.addEvent("domready", function(){ $$('.storage').each(function(el){ el.store('clickCounter', 0); }); document.body.addEvent("click", function(event){ var elmt = new Event(event).target; if(elmt.getProperty('class') == 'storage'){ var counter = elmt.retrieve('clickCounter'); counter++; elmt.store('clickCounter', counter); stats(); // <-- wywołanie funkcji stats } }); stats(); // pierwsze wywołanie dla zainicjalizowania });
Cały powyższy przykład w akcji:
Dla treningu
W ramach utrwalenie sobie poznanych metod klasy Element proponuję stworzyć dwa skrypty:
- Zmieniający atrybuty href oraz title linka znajdującego się pod trzema obrazkami - zmiana atrybutów ma następować po kliknięciu na dany obrazek - link ma zmieniać swoje cechy tak by dopasować je do obrazka,
- Skrypt powiązany z prostą wyszukiwarką na stronie (zwykły input typu text oraz przycisk "Szukaj") zawierającej kilka obrazków, który sprawi, że po kliknięciu przycisku "Szukaj" nastąpi przeszukanie atrybutów title wszystkich obrazków i zmianę klasy obrazka na inną w momencie wykrycia danej frazy w atrybucie title obrazka. Opcjonalnie można rozbudować "wyszukiwarkę" tak by wyszukiwała tylko wśród obrazków oznaczonych odpowiednią klasą - na przykład do obrazków o rozmiarach mniejszych niż określone (atrybuty width i height) byłaby dodawana klasa small, a pozostałym klasa big.
Podsumowanie
Wiemy już jak tworzyć nowe elementy dokumentu, jak operować na większości cech elementu, a także jak wykorzystywać elementy do przechowywania danych. W kolejnej części kursu zajmiemy się głównie umieszczaniem elementów w dokumencie ich niszczeniem, a także zajmiemy się elementem iframe.
Komentarze do wpisu "MooTools 1.2 - elementy strony cz. 2":
1.
metaxy napisał(a):
08 września 2008, 08:59:06
Proponuje zaznaczyć fakt, że dla metody set, czy też obiektu właściwości elementu podczas tworzenia elementu, istnieje istotna różnica między „text”, a „html”.
$(el).set(‘text’, ‘'’); // wstawi literalnie tekst tak jak wpisano
$(el).set(‘html’, ‘'’); // wstawi znak apostrofu
Jest to szczególnie istotne przy odbieraniu danych z MySQL pobieranych przez Request (często znaki specjalne są dla bezpieczeństwa zamieniane na entities).
2.
Piter2k1 napisał(a):
22 września 2009, 01:16:17
W poprzedniej części wspominałeś o ramkach Iframe. Szkoda że jeszcze nie ma nic na ich temat otóż nie potrafię dojść do tego jak dostać się do elementów strony w iframe? Próbowałem tworzyć "new IFrame..." i coś z tym robić ale bezskutecznie... Czy jest jakieś rozwiązanie? Pozdrawiam!
3.
Dziudek napisał(a):
22 września 2009, 11:15:58
@Piter2k1 - jeżeli chodzi o IFrame należy zacząć od tego, że ważne jest czy strona w IFrame pochodzi z tej samej domeny czy nie. Jeżeli nie - to nie można zbytnio na takiej zawartości operować (podobne obostrzenia co w wypadku cross-site XMLHttpRequest). Jeżeli jednak dana strona jest w naszej domenie to dostęp do zawartości jest prosty - dostajemy się do samego elementu IFrame, a potem do elementów odwołujemy się tak jakby to był zwykły dokument - przy czym w obrębie obiektu IFrame.
4.
Someone napisał(a):
04 kwietnia 2010, 19:29:33
Hej, mam problem IFrame. Mianowicie mam powiększanie zdjęć z miniaturek, jednak całość jest w ramce wbudowanej i chciałbym by klikając na link powiększało się na stronie, a nie w ramce. Dodanie do linka target _parent nie daje żadnych rezultatów.
Jest na to rozwiązanie?
Dodaj komentarz: