Mootools 1.1 - Fx.Slide.js
13 sierpnia, 2007
Przyszła pora na ostatni plik z grupy Effects - fx.slide.js, który służy do zwijania i rozwijania elementów, zarówno w pionie jak i w poziomie. Wcześniej do tego celu były używane klasy Fx.Width i Fx.Height, które pewnie niektórzy znają z mojego kursu moo.fx .
Zaletą w stosunku do klas Fx.Width i Fx.Height jest fakt iż ukrywanie elementu nie zmienia jego rozmiaru - nie zobaczymy zatem "upychania" zawartości na coraz mniejszym obszarze jak miało to miejsce w przypadku wspomnianych klas.
Klasa Fx.Slide bo to jej poświęcimy uwagę w tej części kursu, posiada 5 metod:
- slideIn
- slideOut
- show
- hide
- toggle
Dwie pierwsze metody służą odpowiednio do pokazywania i ukrywania elementu, dwie kolejne metody służą do tego samego tyle, że bez stosowania animacji, a ostatnia metoda służy do pokazywania/ukrywania elementu w zależności od tego czy jest on ukryty czy nie.
Efekt slide, jest bardzo często stosowany w Internecie, bo pozwala na ukrycie mniej istotnych informacji do momentu kliknięcia jakiegoś elementu, który je pokaże, poza tym pozwala też na przykład na ukrywanie przez użytkownika mniej ważnych dla niego zawartości itd. Krótko mówiąc możliwości zastosowania ograniczone tylko naszą wyobraźnią :)
Nasze działania skupią się dziś wokół trzech przykładów - pierwszego z ukrywaniem pionowym treści kilku akapitów, drugiego związanego z ukrywaniem poziomym i trzeciego w którym dzięki analizie kodu pliku fx.slide.js stworzymy sobie w prosty sposób pewne udogodnienie, ale o tym później :)
Tworzenie efektu slide jest oczywiście bardzo podobne do tworzenia efektów pozostałych typów. Składnia wygląda następująco:
var slider = new Fx.Slide('id_elementu', {opcje});
Poza standardowymi opcjami jakie klasa Fx.Slide dziedziczy z klasy Fx.Base, dochodzi jeszcze opcja mode - która określa kierunek animacji - vertical (pionowy) lub horizontal (poziomy).
Zatem stworzenie pionowego efektu slide polega na stworzeniu obiektu z użyciem opcji mode ustawionej na vertical:
var slider = new Fx.Slide('div_testowy',{mode: 'vertical'});
W praktyce jednak wystarczy zapis:
var slider = new Fx.Slide('div_testowy');
ponieważ domyślną wartością opcji mode jest właśnie 'vertical'.
Jak wspominałem pierwszy przykład będzie służył zwijaniu bloków teksty (akapitów). Przyjmijmy, że rozwijać/zwijać akapity ma użytkownik poprzez kliknięcie odpowiedniego nagłówka tekstu. Oczywiście moglibyśmy stworzyć teraz po kolei efekty slide i dodać zdarzenia do odpowiednich nagłówków, ale z reguły taka struktura jest powtarzalna - jest określona liczba nagłówków i paragrafów. Dlatego by uelastycznić kod skorzystamy z pętli, która automatycznie stworzy efekty i doda zdarzenia onclick do nagłówków. Dzięki temu dodanie kolejnych nagłówków i paragrafów tekstu nie będzie wymagało zmiany skryptu, a jedynie skorzystania z określonej struktury kodu.
Nasze nagłówki będą miały przypisaną klasę "naglowek", a paragrafy klasę "akapit".
Z akapitów tworzymy tablicę :
var tab_p = $$(".akapit");
A na tablicy nagłówków wykonujemy bezpośrednio nasze operacje - na początek stworzenie efektu slide:
$$(".naglowek").each(function(element,index){
var slider = new Fx.Slide(tab_p[index]);
});
Następnie dodajemy zdarzenie onclick do samego nagłówka:
$$(".naglowek").each(function(element,index){
var slider = new Fx.Slide(tab_p[index]);
element.addEvent("click",function(){
slider.toggle();
});
});
I powyższy kod w połączeniu z odpowiednią strukturą kodu pozwoli nam uzyskać efekt taki jak w poniższym przykładzie:
Jak widzicie pierwszy przykład jest banalny w implementacji. Gdyby ktoś chciał go umieścić na swojej stronie to oczywiście wypadałoby dopisać zapis w cookies informacji o tym, które paragrafy są ukryte. Ale to już zadanie dla tych, którzy chcą ten efekt u siebie mieć ;)
W kolejnym przykładzie zajmiemy się trochę bardziej złożonym zadaniem. Każdy pewnie kojarzy efekt accordion, a jak nie kojarzy to polecam spojrzeć na stronkę biblioteki moo.fx. My stworzymy działający na tej samej zasadzie efekt, ale w poziomie. Jakie są założenia działania naszego skryptu ? Przede wszystkim zawsze musi być widoczny tylko jeden rozwinięty element. Kliknięcie na przycisk aktywujący drugi element musi ukryć ten poprzedni. Pewnie sposobów na napisanie tego typu skryptu jest wiele więc będziecie mogli pokombinować co zmienić i ulepszyć :)
Element naszej układanki będzie składał się z aktywatora i akapitu - kliknięcie na aktywator będzie rozwijało akapit. Pierwszy akapit będzie od razu rozwinięty - pozostałe będą ukryte. Aby nie rozbijać struktury strony będziemy musieli wykorzystać małą sztuczkę - wszystkie akapity poza pierwszym ukryjemy za pomocą stylu display:none; a następnie przy ładowaniu strony zmienimy ten styl na display:block; i oczywiście od razu zastosujemy metodę hide. No ale po kolei: zacznijmy od przygotowania sobie potrzebnych w tym skrypcie zmiennych - nasze paragrafy musimy umieścić w tablicy - a na tablicy aktywatorów wykonamy przypisanie wszystkich parametrów:
var tab_p = $$(".akapit");
Przyda się też zmienna przechowująca informację o tym, który paragraf jest aktualnie rozwinięty :
var aktualny_p = 0;
Zaczynamy od 0 bo tak samo są liczone indeksy w tablicach - po co wykonywać później zbędne operacje dodawania ?
Przyda się jeszcze tablica w której będziemy trzymali nasze efekty:
var tab_e = [];
Przy każdym aktywatorze musimy wykonać następujące operacje: stworzenie efektu, zapisanie efektu w tablicy, dodanie zdarzenia onclick do aktywatora, nadanie paragrafowi (poza pierwszym) atrybutu style="display: block;" i ukrycie go metodą hide. Dodatkowo tworzonemu przez klasę Fx.Slide divowi nadrzędnemu nadawany jest styl float:left tak aby nie następowało rozbicie elementów na kilka linii.
Zatem:
$$(".aktywator").each(function(element,index){
var slider = new Fx.Slide(tab_p[index],{mode: "horizontal"});
tab_e[index] = slider;
if(index > 0){
tab_p[index].setStyle("display","block");
slider.hide();
tab_p[index].getParent().setStyle("float","left");
}
else{
tab_p[index].getParent().setStyle("float","left");
}
element.addEvent("click",function(){
if(aktualny_p !== index){
tab_e[aktualny_p].slideOut();
aktualny_p = index;
tab_e[index].slideIn();
}
});
});
Z powyższego kodu chyba tylko kod zdarzenia onclick przypisywanego do aktywatora może wydać się skomplikowany, dlatego już tłumaczę - na początku sprawdzane jest czy chcemy rozwinąć już rozwinięty element - jeżeli tak to nic się nie stanie bo chcemy aby zawsze co najmniej jeden element był rozwinięty. W drugim wypadku aktualnie rozwinięty element jest ukrywany (zwijany), następuje zmiana wartości zmiennej przechowującej informację o aktualnie otwartym paragrafie i zostaje rozwinięty paragraf do którego jest przypisany klikany aktywator.
I powyższy kod w akcji:
Na koniec opiszę małe usprawnienie dla klasy Fx.Slide, które może się niektórym przydać. Posiada ona małą wadę, otóż animacja przebiega tylko w jedną stronę ustaloną przez programistów mootools. A co jeśli chcielibyśmy, żeby zwijanie/rozwijanie pionowe przebiegało od dołu do góry, a nie od góry do dołu (tzn. aby przy zwijaniu pionowym dolna krawędź przemieszczała się do góry, powodując tym samym widoczność tekstu w górnej części elementu do końca) ? Jest to do zrobienia. Gorzej w wypadku animacji poziomej - jeżeli chcemy ukrywać element poprzez jego odsunięcie w prawą stronę to zamiast przerabiać klasę Fx.Slide lepiej stworzyć div w divie i nadać im tą samą szerokość, a następnie operować na właściwości margin-right wewnętrznego diva (oczywiście ba divy muszą mieć ustawione overflow:hidden).
Natomiast jeśli chodzi o zwijanie pionowe to musimy dodać do naszego skryptu taki kod:
Fx.Slide.implement({
vertical: function(){
this.margin = 'margin-bottom';
this.layout = 'height';
this.offset = this.element.offsetHeight;
}
});
Zmieniamy właściwość this.margin z "margin-top" na "margin-bottom" i to wystarczy by efekt przebiegał w inny sposób. Oczywiście zmiany dotyczą całej klasy Fx.Slide. Jeśli chcemy mieć dostęp do obu typów pionowych animacji to musimy stworzyć klasę potomną klasy Fx.Slide i dopiero do niej dopisać powyższy kod:
Fx.SlideReverse = Fx.Slide.extend({
vertical: function(){
this.margin = 'margin-bottom';
this.layout = 'height';
this.offset = this.element.offsetHeight;
}
});
Oczywiście dalej tworzymy efekt na tej samej zasadzie co wcześniej.
Ja z tego rozwiązania skorzystałem w swoim przykładzie po to by łatwo było zauważyć różnicę pomiędzy oboma typami animacji:
I to już wszystko na temat nie tylko klasy Fx.Slide, ale i grupy Effects. W dwóch kolejnych częściach kursu zajmiemy się grupą Drag
Komentarze do wpisu "Mootools 1.1 - Fx.Slide.js":
1.
Koval napisał(a):
13 sierpnia 2007, 10:18:46
powiedz mi jak przykład 2 ma się do joggera, bo kiedyś coś takiego chciałem zrobić u siebie ale staneło na panewce
2.
Koval napisał(a):
13 sierpnia 2007, 10:19:46
chodzi mi o uzycie tego na wpisy
3.
Dziudek napisał(a):
13 sierpnia 2007, 15:01:44
Koval – według mnie dałoby radę to zrobić na joggerze i w ten sposób prezentować wpisy tylko problem jest z osobami mającymi wyłączony JS – wtedy trzeba pokombinować ze znacznikami
noscript.Zauważ, że masz regularną strukturę – aktywator, akapit, aktywator, akapit – więc wygenerowanie tego za pomocą joggera to nie problem, ewentualnie nie generujesz id „pierwszy” tylko nadajesz
display:blockza pomocą JS.4.
Koval napisał(a):
13 sierpnia 2007, 17:03:34
no wlasnie wylaczenie js to jest problem, ale
5.
Koval napisał(a):
13 sierpnia 2007, 17:04:05
dzieki za info. pobawie sie kiedys
6.
coldpeer napisał(a):
15 sierpnia 2007, 14:35:26
Miało być > zamiast >> ;-)
7.
Dziudek napisał(a):
15 sierpnia 2007, 19:53:12
@coldpeer – rzeczywiście :) Chyba podczas poprawiania encji się pomyliłem ;) Dzięki za info :)
8.
plejeru napisał(a):
29 sierpnia 2007, 11:22:56
a jak zrobić tak, żeby się klatki zmieniały same co parę sekund, ale można było też kliknięciem przechodzić? (takie cuś jak na wp np.)
9.
Dziudek napisał(a):
29 sierpnia 2007, 20:16:19
@plejeru – sprawa jest w sumie prosta – po załadowaniu strony odpalasz okresowo funkcję i ustawiasz zmienną która mówi o stanie odtwarzania animacji – gdy user kliknie na dany element to zmieniasz stan animacji i zatrzymujesz okresowo wykonywaną funkcję. Zmienna mówiąca o stanie animacji jest oczywiście potrzebna do przycisku ją uruchamiającego ;)
10.
plejeru napisał(a):
29 sierpnia 2007, 20:18:01
Ahaaaa… <czyta jeszcze raz, spokojnie i na glos> ;)
11.
plejeru napisał(a):
29 sierpnia 2007, 20:20:46
Dobra, czytam o function.js :D
12.
Dziudek napisał(a):
29 sierpnia 2007, 20:23:09
@plejeru – i funkcja $clear się przyda ;]
13.
jako napisał(a):
05 września 2007, 15:32:51
A jak rozpocząć z ukrytymi elementami? -> (przykład 1)
Byłbym wdzięczny za podpowiedz :)
14.
Dziudek napisał(a):
05 września 2007, 15:37:40
jako – nadaj elementom
display:nonew CSS (oczywiście warto pamiętać o użytkownikach z wyłączonym JS – dla nich w znacznikunoscriptustawdisplay:block), następnie przy ładowaniu strony (zdarzeniedomreadylubloadobiektuwindow) nadaj tym elementom poprzez metodęsetStyleatrybutdisplay:blocki zaraz po tym uruchom metodęhideklasyFx.Slideprzypisanej do tych elementów – dzięki temu elementy przy ładowaniu strony będą niewidoczne a zaraz po załadowaniu zostaną w niezauważalny sposób pokazane i ukryte od razu przez JS ;)15.
jako napisał(a):
05 września 2007, 16:15:01
Dziudek dziękuję za szybką odpowiedz…jest jeden problem, js to dla mnie start i ciężko mi będzie poprawnie ten kod „zbudować” :
| Jeżeli nie jest to „zbyt dużo” to milo było by otrzymać całkowity wygląd kodu js, lub coś co mi to ułatwi. Choć pewnie wcześniejsza odpowiedz powinna wystarczyć...ale cóż, niewiedze trudno przeskoczyć :)16.
Dziudek napisał(a):
05 września 2007, 16:28:17
@jako – obejrzyj ten przykład
17.
jako napisał(a):
05 września 2007, 16:41:07
Dziudek > serdecznie dzięki za pomoc… i gratuluje interesującego blog’a!
18.
tomq napisał(a):
06 listopada 2007, 23:30:15
Witam,
Mam pytanie – jak zrobić efekt slide w drugą stronę? Tzn. z dołu do góry i z prawej do lewej rozsuwanie? :>
pozdrawiam,
Tomasz.
19.
Dziudek napisał(a):
06 listopada 2007, 23:45:55
@tomq – zobacz ostatni przykład z powyższego wpisu i komentarz z kodem powyżej niego ;)
20.
hunter napisał(a):
17 listopada 2008, 12:39:59
A jak zrobić aby strona się zwiększała. U mnie pozostaje przy tych samych wymiarach.
21.
Kipst napisał(a):
03 grudnia 2008, 13:09:04
Witam. Bardzo przydał mi się opis jak wykorzystać Fx.Slide. Aktualnie próbuje przekształcić trochę skrypt aby dana sekcja (np. div) po przejściu na podstrone została odkryta. Pomyślałem o rozwiązaniu aby na tej podstronie zamienić klase elementu „akapit” na nowa np. „akapit_aktualny”
Ponizej kawalek struktury kodu menu strony
<li class=„naglowek”>1 kawalek</li>
<div class=„akapit_aktualny”>
<a href=”#”>1 podstrona</a>
<a href=”#”>2 podstrona</a></div><li class=„naglowek”>2 kawalek</li>
<div class=„akapit”>
<a href=”#” >1 podstrona</a>
<a href=”#”>2 odstrona</a>
</div>
w kodzie JS elementy „akapit” ukrywam a „elementy „akapit_aktualny” chce aby byly widoczne. Narazie mam taki kawalek kodu, ktory nie dziala jak nalezy:
window.addEvent(„load”,function(){ var tab_p = $$(”.akapit”); var akapit_aktualny= $$(”.akapit_aktualny”); var aktualny_p = 0; var tab_e = [];
$$(”.naglowek”).each(function(element,index){ var slider = new Fx.Slide(tab_p[index]); tab_e[index] = slider; slider.hide(); /** Rozwiń aktualny dział – na podstawie klasy akapit_aktualny*/ var slider_aktualny = new Fx.Slide(akapit_aktualny[index]); slider_aktualny.slideIn();
/**element.addEvent(„click”,function(){ slider.toggle(); **/ element.addEvent(„click”,function(){ if (aktualny_p ==0 && index ==0) { tab_e[index].slideIn(); } else if (aktualny_p !== index){ tab_e[aktualny_p].slideOut(); aktualny_p = index; tab_e[index].slideIn(); } }); });
});
Jeśli mógłbym prosić o wskazówkę jak do tego podejść był bym wdzięczny. Pozdrawiam Grzesiek
22.
Dziudek napisał(a):
04 grudnia 2008, 09:03:56
@Kipst – na pierwszy rzut oka:
Fx.Slide(akapit_aktualny[index]);nie powinno być:
Fx.Slide(akapit_aktualny[0]);? Nie wspomnę, że zamiast :
$$(”.akapit_aktualny”);można użyć:
$E(”.akapit_aktualny”);Skoro i tak jest tylko jeden taki akapit ;)
Jak będzie więcej problemów to proszę pisz na mój email – dziudek[at]gmail[dot]com – szybciej dostaniesz odpowiedź ;)
Dodaj komentarz: