Mootools 1.1 - Drag.Base.js
17 sierpnia, 2007
Dziś rozpoczynamy ostatnią, że tak to ujmę "zwartą" grupę plików frameworka mootools - po niej pozostaną do omówienia już tylko pluginy, które mają między sobą dość luźne powiązania lub nie mają ich wcale. Sekcja Drag zawiera dwa pliki - omawiany w tej części plik drag.base.js i będący tematem następnej części kursu drag.move.js .
Plik drag.base.js służy do realizacji dwóch zadań - przenoszenia elementów oraz zmiany ich rozmiarów. Przy czym implementacja przenoszenia elementów jest dość uboga w tym pliku i tak naprawdę pełnię drag & drop zobaczymy dopiero przy omawianiu drugiego pliku sekcji Drag.
Zadania jakie postawimy sobie na dziś to : stworzenie elementu div, który będzie można swobodnie przenosić oraz projekt ulepszonego pola textarea.
Zaczniemy jak zwykle od dawki teorii.
Klasa Drag.Base pobiera dwa argumenty - element, którego mają dotyczyć modyfikacje i obiekt opcji:
new Drag.Base("element",{opcje});
W czasie działania obiektu tej klasy mamy do dyspozycji 5 zdarzeń:
- onBeforeStart - zdarzenie występujące przed rozpoczęciem operowania na elemencie - przydatne w momencie, gdy potrzebujemy zmienić parametry obiektu przed samą akcją.
- onStart - zdarzenie to występuje w momencie ustawienia parametrów dla modyfikacji elementu.
- onSnap - zdarzenie, które występuje przy przekroczeniu limitu określonego w opcji snap.
- onDrag - zdarzenie to występuje w momencie rozpoczęcia przenoszenia elementu.
- onComplete - zdarzenie wywoływane w momencie zakończenia modyfikacji elementu.
Oprócz tego mamy do dyspozycji dużo opcji:
- handle - element jaki będzie służył do modyfikacji parametrów - domyślnie jest to element podany jako argument klasy Drag.Base,
- modifiers - obiekt posiadający dwa pola - x oraz y do których przypisane są nazwy właściwości modyfikowanych w czasie ruchu myszą. Domyślnie dla x przypisana jest właściwość left, a dla y właściwość top,
- limit - podobny obiekt jak w wypadku opcji modifiers z tą różnicą, że wartością jest tablica, której pierwszy i drugi element odpowiada przedziałowi w jakim mogą się dokonywać modyfikacje - zarówno w pionie jak i w poziomie.
- snap - opcja ta zawiera dystans jaki musi przebyć kursor myszki aby rozpocząć operację modyfikacji elementu. Domyślnie opcja ta ma wartość 6 (oznacza to, że po wciśnięciu klawisza myszy, możemy przebyć kursorem dystans 5 pikseli i element nie zostanie przesunięty).
- grid - dzięki tej opcji możemy sprawić, że zamiast płynnej zmiany wartości będą się one zmieniały co określoną wielkość - na przykład 10 pikseli. Domyślnie opcja ta jest wyłączona.
- unit - jednostka w jakiej dokonywane są modyfikacje. Domyślnie piksele - "px".
Poza klasą Drag.Base w tytułowym pliku jest jeszcze metoda makeResizable - służy ona do automatycznego tworzenia możliwości zmiany rozmiaru elementu. Jej składnia wygląda następująco :
element.makeResizable({opcje});
Gdzie obiekt {opcje} to oczywiście wspomniane wcześniej parametry, ale nie ma sensu ustawiać opcji modifiers bo i tak jest ona już domyślnie ustawiona na width i height elementu. Ale najpierw zajmijmy się prostym przykładem przenoszenia elementu.
Jak zrobić nasz pierwszy przenośny element ? Sprawa jest niesamowicie banalna - wymaga dodania 4 linijek kodu - 3 JavaScript i jednej CSS przy czym samo utworzenie przenośnego elementu to jedna linijka, a dwie pozostałe odpowiadają za zdarzenie onload obiektu window :)
Zatem elementowi, których chcemy przenosić nadajemy właściwość:
position: absolute;
Oraz tworzymy następujacy kod JS:
new Drag.Base("przenosny");
Oczywiście kod ten umieszczamy w zdarzeniu onload obiektu window - myślę, że powinniście już mieć to we krwi ;) Jak widzicie nasz div ma identyfikator przenosny co całkiem dobrze oddaje jego możliwości:
No dobrze - przykład z serii "prościej już się nie da" mamy za sobą ;) Pora na coś bardziej złożonego. Zapoznajmy się bliżej z opcją snap, oraz ze zdarzeniami onSnap i onDrag - nasz poprzedni przykład ulepszymy o opóźnienie rozpoczęcia przenoszenia (snap), które wystąpi dopiero po przemieszczeniu się przez kursor myszy o 20 pikseli, a dodatkowo w wypadku gdy wystąpią zdarzenia onSnap i onDrag pojawi się stosowny komunikat w elemencie.
Do naszego obiektu klasy Drag.Base dodajemy obiekt z odpowiednimi parametrami:
new Drag.Base("przenosny",{
snap: 20,
onSnap: function(){
this.element.innerHTML = "Snap";
},
onDrag: function(){
this.element.innerHTML = "Drag";
}
});
Warto zwrócić uwagę na odwołanie this.element przy tworzeniu klasy - pozwala mi ono odwołać się do przenoszonego diva, bez jego ponownej selekcji z drzewa dokumentu.
I powyższy kod w akcji (aby zobaczyć napis "Snap" zalecam wolne przesuwanie myszką gdyż występuje on tylko po przebyciu 20 pikseli, a potem zaraz znika na rzecz napisu "Drag"):
Zanim przejdziemy do przykładu z polem textarea, jeszcze jeden przykład z naszym przenośnym divem - dodamy dwa przyciski, które pozwolą nam decydować czy ruch diva ma się ograniczać do ruchu poziomego lub pionowego. Wykorzystamy do tego zdarzenie onBeforeStart i opcję modifiers.
Na początku tworzymy sobie zmienną przechowującą informacje o aktualnej możliwości ruchu:
var mozliwosci_ruchu = false;
Na początek będzie ona pozbawiona wartości, bo będziemy ją zmieniać za pomocą dwóch przycisków - pion i poziom. Dodajmy do tych przycisków zdarzenia onclick:
$("pion").addEvent("click",function(){
mozliwosci_ruchu = "pion";
});
$("poziom").addEvent("click",function(){
mozliwosci_ruchu = "poziom";
});
Mając te "przełączniki" wystarczy już tylko stworzyć odpowiednia funkcję dla zdarzenia onBeforeStart - musi ona w zależności od żądanego kierunku ruchu zmieniać opcję modifiers tak by tylko jedna modyfikacja była dokonywana w czasie ruchu myszą. Osiągamy to poprzez przypisanie do jednej z właściwości obiektu wartości false:
new Drag.Base("przenosny",{
onBeforeStart: function(){
switch(mozliwosci_ruchu){
case "pion": this.modifiers = {x: false, y: "top"};break;
case "poziom": this.modifiers = {x: "left", y: false};break;
default:;break;
}
}
});
I to właściwie wszystko co trzeba było napisać:
No to teraz jeszcze krótka, ale bardzo istotna uwaga - otóż zarówno na IE jak i na Safari 3 powyższe przykłady nie zadziałałyby gdyby w stylu CSS dla diva "przenosny" nie byłyby ustawione właściwości top i left - bez ich określenia, chociażby:
top: 0;
left: 0;
efekt zadziała tylko pod Firefoksem i Operą...
Pora na zajęcie się polem textarea - użytkownicy Joggera pewnie nie zaprzeczą iż rozciągane pole tego typu to świetna sprawa, zwłaszcza dla posiadaczy większych monitorów :) Zatem przygotujemy rozciągane pole textarea. Będzie je można rozciągać wzdłuż, ale tylko w ograniczonym zakresie, dla małego upiększenia, podczas zmiany rozmiarów pola będzie zmieniane jego obramowanie.
Zaczniemy oczywiście od podstaw, czyli pola textarea, które można rozciągać do dowolnych rozmiarów, przemieszczając odpowiedni element. Nasze pole textarea będzie posiadało identyfikator "text", a element służący do rozciągania tego pola będzie miał identyfikator "suwak". Dodajemy metodę makeResizable do naszego pola:
$("text").makeResizable();
Następnie dodajemy opcję handle, a jako jej wartość podajemy nasz suwak:
$("text").makeResizable({
handle: "suwak"
});
Po tych operacjach nasz przykład prezentuje się następująco:
Ale wciąż nie ma ograniczenia na zmianę szerokości elementu. Ponieważ przy wywołaniu makeResizable modyfikowane parametry są narzucane z góry, musimy skorzystać ze zdarzenia onBeforeStart i zmienić właściwość pola x obiektu modifiers:
$("text").makeResizable({
handle: "suwak",
onBeforeStart: function(){
this.options.modifiers.x = false;
}
});
Teraz już wszystko powinno działać poprawnie:
Pora na ostatni efekt - zmianę stylu obramowania pola textarea na czas rozciągania. Skorzystamy tutaj z dwóch zdarzeń - onStart i onComplete. Zdarzenie onStart będzie zmieniało obramowanie na wykropkowane, a przy zdarzeniu onComplete będzie przywracane normalne obramowanie:
$("text").makeResizable({
handle: "suwak",
onBeforeStart: function(){
this.options.modifiers.x = false;
},
onStart: function(){
this.element.setStyle("border-style","dotted");
},
onComplete: function(){
this.element.setStyle("border-style","solid");
}
});
Przyda się jeszcze ograniczenie możliwości rozciągania elementu (opcja limit) - powiedzmy, ze minimalną wysokością ma być 100 pikseli, a maksymalną 500 pikseli. Ponieważ nie interesuje nas szerokość jako wartość pola x podajemy false, a jako wartość pola y wspomniany przedział w postaci tabeli:
$("text").makeResizable({
handle: "suwak",
limit: {
x: false,
y: [100,500]
},
onBeforeStart: function(){
this.options.modifiers.x = false;
},
onStart: function(){
this.element.setStyle("border-style","dotted");
},
onComplete: function(){
this.element.setStyle("border-style","solid");
}
});
I w ten sposób otrzymamy poniższy efekt:
Jeżeli ktoś ma ochotę dopieścić jeszcze bardziej to pole textarea, to osobiście proponuję by zastosować opcję grid tak by wysokość pola była zawsze iloczynem pewnej liczby linii tekstu (obecnie można "uciąć" linijkę tekstu w połowie wysokości podczas zmiany rozmiaru elementu).
W następnej części kursu zajmiemy się plikiem drag.move.js i będziemy kontynuowali naszą naukę obsługi przenośnych elementów :)
Komentarze do wpisu "Mootools 1.1 - Drag.Base.js":
1.
wojcieh napisał(a):
17 sierpnia 2007, 23:02:05
bardzo podobaja mi sie Twoje artykuly – jak bede w prztszlosci tworzyl swoja strone internetowa napewno uzyje czesci Twoich opracowan z kursu :)
pozdrawiam Wojtek
Dodaj komentarz: