Skrypty JavaScript ułatwiające przetwarzanie formularzy
Oprogramowanie formularza w języku
JavaScript niesie za sobą kilka korzyści,
które zwiększają komfort pracy użytkownika.
Typowymi przykładami są wstępne sprawdzenie
poprawności danych bez konieczności kontaktu z serwerem,
ograniczenie powierzchni zajmowanej przez formularz dzięki zastosowaniu kontrolek,
które automatycznie wysyłają formularz, wymuszenie poprawnych danych poprzez zablokowanie
niedozwolonych klawiszy czy wyświetlanie znikających podpowiedzi w polach tekstowych
(podpowiedzi znikają po umieszczeniu kursora wewnątrz kontrolki).
W artykule omówimy najczęściej spotykane skrypty
JavaScript,
które ułatwiają wypełnianie formularzy.
Przenoszenie kursora do kontrolki formularza
Przyjrzyjmy się formularzowi przedstawionemu na rysunku 1.
Po wyświetleniu takiej witryny w
przeglądarce, kursor będzie znajdował się
poza formularzem. Żadna z kontrolek nie będzie aktywna.
Jeśli teraz z klawiatury wprowadzimy tekst, wówczas nie trafi on
do żadnego z pól formularza.
Wprowadzanie danych musimy poprzedzić wyborem kontrolki.
Stosujemy albo klawisz tabulacji, albo klikamy w wybraną kontrolkę myszką.
Rys. 1.
Kursor umieszczamy w trzecim polu formularza.
W niektórych przypadkach warto formularz przygotować w
taki sposób, by jedna z jego kontrolek była aktywna od razu po
wyświetleniu witryny w przeglądarce.
Takie zachowanie będzie wygodne na przykład w odniesieniu
do formularzy umożliwiających logowanie lub wyszukiwanie informacji.
Umieszczenie kursora w jednym z pól formularza wymaga trzech elementów w
kodzie witryny.
Po pierwsze musimy przygotować funkcję fokus(),
która uaktywni wybraną kontrolkę.
Kod takiej funkcji jest przedstawiony na listingu 1.
Parametr AElementID
jest identyfikatorem, czyli wartością atrybutu id,
elementu, który ma zostać uaktywniony.
function fokus(AElementID) { var el = document.getElementById(AElementID); el.focus(); }
Listing 1.
Kod funkcji fokus().
Po drugie funkcja fokus()
musi zostać wywołana w momencie wyświetlania strony.
Zatem jako skrypt obsługi zdarzenia onload
elementu BODY
podajemy funkcję fokus() z
identyfikatorem kontrolki, która ma zostać uaktywniona:
<BODY onload="fokus('poleemail');"> ... <INPUT name="email" id="poleemail"> ... </BODY>
Wreszcie ostatnim, trzecim, etapem jest nadanie atrybutu id
wybranej kontrolce formularza.
W powyższym przykładzie, kontrolka
INPUT posiada oprócz atrybutu
name o wartości
email również atrybut id="poleemail".
Wartość poleemail jest przekazywana do
funkcji fokus().
Po wyświetleniu tak przygotowanej strony, kursor zostanie przez przeglądarkę automatycznie
umieszczony w polu tekstowym, które służy do wprowadzania adresu email.
Użytkownik może od razu rozpocząć wprowadzanie adresu, bez konieczności
klikania w pole tekstowe czy kilkukrotnego naciskania klawisza tabulacji.
Powyższy kod JavaScript możemy napisać na kilka sposobów.
Na przykład stosując obiekt document
i tablice forms oraz elements:
document.forms[0].elements[2].focus();
Jednakże pierwsze z podanych rozwiązań jest chyba najbardziej wygodne w użyciu.
Kod funkcji fokus jest uniwersalny i nie ulega zmianie bez względu
na modyfikacje kodu witryny, w szczególności formularza oraz jego kontrolek.
Jedynymi zmianami, jakie trzeba wykonać, są nadanie atrybutu
id odpowiedniej kontrolce oraz
modyfikacja obsługi zdarzenia onload
(należy podać identyfikator elementu, jaki ma zostać uaktywniony).
Spakowane archiwum 1-aktywne-miejsce.zip
zawiera kilka przykładowych rozwiązań opisanego problemu wraz ze wskazaniem
ich potencjalnych wad i zalet.
Walidacja formularza
Po wybraniu aktywnego elementu formularza przejdźmy do sprawdzenia
poprawności danych wprowadzonych przez użytkownika.
Walidajca formularza jest wykonywana podczas obsługi zdarzenia
onsubmit elementu FORM:
<FORM action="..." onsubmit="return validateForm(this);"> ... </FORM>
Funkcja validateForm() zwraca wartość
logiczną.
W przypadku, gdy dane zawarte w formularzu spełniają nakładane ograniczenia,
wynikiem funkcji powinna być wartość true,
w przeciwnym razie — false.
Parametr this przekazywany do funkcji jest referencją
do obiektu FORM, wewnątrz którego występuje wywołanie funkcji
validateForm().
Kod funkcji, przedstawiony na listingu 2, jest oczywiście przystosowany do walidacji
konkretnego formularza.
O ile funkcja do wyboru aktywnej kontrolki może być przygotowana w sposób
uniwersalny (tj. taki, by nadawała się do wielu różnych formularzy), to
skrypt sprawdzający poprawność jest dostosowany do konkretnego przypadku i trudno tutaj
mówić o uniwersalności takiego czy innego rozwiązania.
function validateForm(AForm) { if (!(AForm.soft1.checked || AForm.soft2.checked || AForm.soft3.checked || AForm.soft4.checked || AForm.soft5.checked)) { alert("Wypełnij przynajmniej jedno pole!"); return false; } else { return true; } }
Listing 2.
Funkcja validateForm() wymagająca, by jedno z pól typu checkbox zostało zaznaczone.
Formularz sprawdzany funkcją z listingu 2 jest widoczny na rysunku 2.
Posiada on kilka pól typu checkbox.
Kolejne pola nazywają się
soft1,
soft2, ...,
soft5:
<INPUT type="checkbox" name="soft1"> <INPUT type="checkbox" name="soft2">
Procedura walidująca zawarta w kodzie funkcji validateForm() wymaga,
by przynajmniej jedno pole było zaznaczone
(czyli wartość jednego z pól, np. AForm.soft1.checked
musi być równa true).
Komunikat wyświetlany w przypadku błędnego wypełnienia jest widoczny na rysunku 2.
Do wyświetlenia komunikatu służy funkcja alert()
wywoływana wewnątrz funkcji validateForm().

Rys. 2.
Formularz o kilku polach typu checkbox oraz komunikat diagnostyczny informujący o błędnym wypełnieniu. Komunikat jest wyświetlany funkcją alert() wywoływaną wewnątrz funkcji validateForm().
Ogólnie, struktura walidacji formularza w skrypcie JavaScript
przebiega następująco:
-
Przygotowujemy funkcję walidateForm().
- Funkcja ta jest dostosowana do konkretnego formularza.
- Jej jedynym parametrem jest referencja od obiektu będącego walidowanym formularzem.
- Zwracana wartość jest informacją logiczną, mówiącą o poprawności danych zawartych w formularzu.
- W przypadku stwierdzenia błędów, wyświetlane są komunikaty diagnostyczne (funkcja alert()).
-
Element FORM posiada obsługę
zdarzenia onsubmit.
Wywołujemy funkcję validateForm()
przekazując jej obiekt this:
onsubmit="return validateForm(this);"
Inne przykłady funkcji validateForm() są przedstawione
na listingach 3 oraz 4.
function validateForm(AForm) { if (!AForm.imie.value) { alert("Wypełnij pole imię!"); return false; } else { return true; } }
Listing 3.
Funkcja validateForm() wymagająca, by pole o nazwie imie zostało wypełnione.
function validateForm(AForm) { if ((!AForm.imie.value) || (AForm.imie.value.length < 3)) { alert("Wypełnij pole imię, podaj co najmniej trzy znaki!"); return false; } else { return true; } }
Listing 4.
Funkcja validateForm() wymagająca, by pole o nazwie imie zostało wypełnione oraz by wprowadzony napis miał co najmniej trzy znaki.
Wykorzystanie wyrażeń regularnych do walidacji pól
Walidacja wartości wprowadzonych w polach tekstowych zawarta w listingach 3 oraz 4
uwzględnia jedynie najprostsze możliwe testy, tj. stwierdzenie czy pole zostało w ogóle wypełnione
oraz czy liczba wprowadzonych znaków jest odpowiednia.
W przypadku bardziej złożonych testów należy zastosować wyrażenia regularne.
Niech przykładowy formularz zawiera pole
INPUT o nazwie litery:
<INPUT name="litery">
W takim przypadku, wewnątrz funkcji validateForm()
wywołanej z parametrem this w obsłudze zdarzenia
onsubmit elementu FORM),
dostępny będzie napis
AForm.litery.value.
Napis ten kopiujemy do zmiennej str instrukcją:
str = AForm.litery.value;
Następnie, w zmiennej litPatt
przygotowujemy wzorzec ograniczający poprawność danych:
litPatt = /^[A-Z]{3,5}$/;
Podane wyrażenie regularne pasuje do
napisów, które zawierają od 3 do 5 dużych liter alfabetu
łacińskiego (tj. bez polskich „ogonków”).
Następnie wzorzec litPatt dopasowujemy do napisu zawartego w
zmiennej str, wywołując metodę
match():
wynik = str.match(litPatt);
Wynik zwrócony przez funkcję match()
zawiera informację o tym, czy dane wprowadzone w formularzu są zgodne z
podanym wyrażeniem.
Pełny kod funkcji walidującej pole litery
jest przedstawiony na listingu 5.
function validateForm(AForm) { str = AForm.litery.value; litPatt = /^[A-Z]{3,5}$/; wynik = str.match(litPatt);
if (wynik == null) { alert("Napis może zawierać od 3 do 5 dużych liter!"); return false; } else { return true; } }
Listing 5.
Walidacja przy użyciu wyrażeń regularnych.
Oczywiście operacja kopiowania napisu z pola litery
do zmiennej str nie jest konieczna.
Powyższy kod, wykonany z pominięciem zmiennej str, wyglądałby następująco:
litPatt = /^[A-Z]{3,5}$/; wynik = AForm.litery.value.match(litPatt);
Testowanie poprawności kilku pól
Jeśli formularz zawiera wiele pól, wówczas nie możemy ograniczyć się do sprawdzenia
jednego z nich.
Należy sprawdzić poprawność wszystkich pól formularza, lub przynajmniej pól wymaganych.
W takim przypadku funkcja validateForm()
będzie kolejno testowała pola formularza aż do napotkania pierwszego błędu.
Jeśli wszystkie pola uznane zostaną za poprawne, to zwracana
jest wartość true.
W przeciwnym razie, po pierwszym napotkanym niepoprawnym polu,
wyświetlamy komunikat diagnostyczny,
po czym zwracamy wartość false.
Przykład takiej procedury jest przedstawiony na listingu 6.
Jest to procedura sprawdzająca poprawność formularza „Dane osobowe”.
function validateForm(AForm) { //1. Imię reg = /^[a-zA-ZąćęłńóśżźĄĆĘŁŃÓŚŻŹ]{2,20}$/; wyn = AForm.fimie.value.match(reg); if (wyn == null) { alert("Proszę podać poprawne imie. " + "Imie musi zawierać od 2 do 20 liter. " + "Żadne znaki poza literami nie są dozwolone."); return false; }
//3. Płeć if (!(AForm.fplec[0].checked || AForm.fplec[1].checked )) { alert("Proszę zaznaczyć pole 'Płeć'."); return false; };
//3. Email reg = /^[a-zA-Z0-9ąćęłńóśżźĄĆĘŁŃÓŚŻŹ]{1,30}@[a-zA-Z0-9ąćęłńóśżźĄĆĘŁŃÓŚŻŹ]+(\.[a-zA-Z0-9ąćęłńóśżźĄĆĘŁŃÓŚŻŹ]+)+$/; wyn = AForm.femail.value.match(reg); if (wyn == null) { alert("Proszę podać poprawny adres email. " + "Poprawny adres musi zawierać małpę " + "oraz co najmniej dwa człony nazwy serwera, " + "np. a@b.c lub ala@ma.kota.czarnego.com."); return false; }
//4. Województwo if (!(AForm.fwojewodztwo.selectedIndex > 0 && AForm.fwojewodztwo.selectedIndex <= 16)) { alert("Proszę wybrać województwo."); return false; };
return true; }
Listing 6.
Sprawdzenie poprawności kilku pól formularza.
Pierwszym sprawdzanym polem jest pole o nazwie fimie.
Wprowadzona wartość ma być zgodna z wyrażeniem:
reg = /^[a-zA-ZąćęłńóśżźĄĆĘŁŃÓŚŻŹ]{2,20}$/;
czyli ma się składać wyłącznie z liter. Podany napis ma mieć długość od
2 do 20 znaków.
Drugi test dotyczy pól określających płeć. Zaznaczone wartości są dostępne w
tablicy fplec pod indeksami
fplec[0] oraz fplec[1].
Badamy czy przynajmniej jedno z pól zostało zaznaczone.
Trzecie sprawdzane pole zawiera adres email. Tym razem wyrażenie regularne jest nieco
bardziej skomplikowane.
Struktura wyrażenia jest następująca:
reg = /^X@Y$/;
Napis składa się z części oznaczonej jako
X (przed znakiem małpy),
znaku małpy @
oraz części oznaczonej jako Y (po znaku małpy).
Skrót X użyty w powyższym opisie oznacza napis
o długości od 1 do 30 liter składający się z cyfr lub liter (tym razem dopuszczamy „ogonki”):
[a-zA-Z0-9ąćęłńóśżźĄĆĘŁŃÓŚŻŹ]{1,30}
Natomiast symbol Y oznacza napis zgodny z wyrażeniem:
[a-zA-Z0-9ąćęłńóśżźĄĆĘŁŃÓŚŻŹ]+(\.[a-zA-Z0-9ąćęłńóśżźĄĆĘŁŃÓŚŻŹ]+)+
Po uproszczeniu zbioru występującego w dwóch miejscach powyższego
wyrażenia do postaci [A] otrzymamy wyrażenie:
[A]+(\.[A]+)+
Ponieważ znak + oznacza w wyrażeniach regularnych
dowolną liczbę powtórzeń (począwszy od jednego) wyrażenia poprzedzającego,
zaś nawiasy okrągłe grupują człony wyrażenia, zatem podany wzorzec jest zgodny
z napisami:
A.AAAA AA.A.AAA AA.AA.A.AAAA itd.
Reasumując powyższe warunki, wprowadzony adres email musi zawierać:
- znak małpy @;
- przed znakiem małpy od 1 do 30 znaków (liter lub cyfr);
- po znaku małpy: co najmniej dwa człony oddzielone kropką; każdy człon
składa się co najmniej z jednego znaku;
Przykładami adresów, które pasują do podanego wzorca są:
ala@ma.kota a@b.c.d.e john@books.com
zaś niepasującymi:
ala.ma.kota (brak małpy) ala@ma (za mało członów domeny) ala@ma..kota (brak przynajmniej jednej litery pomiędzy kropkami) (ala)@[m].k (niedozwolone znaki)
Ostatni z testów dotyczy pola fwojewodztwo
i polega na sprawdzeniu indeksu wybranego elementu listy
rozwijanej.
Czyszczenie zawartości formularza
Formularz zawierający dane osobowe posiada przycisk do usunięcia zawartości.
Nie służy do tego bynajmniej standardowy
przycisk o kodzie:
<INPUT type="reset" value="Reset">
Działanie powyższego przycisku typu reset
powoduje powrót do wartości, jakimi formularz został zainicjalizowany.
Jeśli w kodzie formularza znajduje się kontrolka:
<INPUT name="imie" value="Janek">
zaś użytkownik wprowadził w polu wartość Janusz,
wówczas naciśnięcie standardowego przycisku do
resetowania zawartości formularza (czyli podanego przycisku
INPUT typu reset)
spowoduje ponowne ustalenie wartości
pola imie na Janek.
Pole nie zostaje wyczyszczone. Jego wartość jest równa — po naciśnięciu przycisku
Reset — wartości ustalonej
atrybutem value.
Jeśli chcemy usunąć wprowadzone wartości (czyli wprowadzić napisy puste do
wierszy wprowadzania danych, odznaczyć wszystkie pola wyboru itd.),
to musimy do tego celu przygotować
specjalny skrypt. Kod funkcji clearForm()
został przedstawiony na listingu 7.
Funkcja ta jest uniwersalna i może zostać użyta w odniesieniu
do dowolnego formularza.
Jej jedynym parametrem jest referencja do obiektu FORM.
function clearForm(AForm) { for (i = 0; i < AForm.elements.length; i++) { if (AForm.elements.type == "radio") { AForm.elements.checked = false; } else if (AForm.elements.type == "checkbox") { AForm.elements.checked = false; } else if (AForm.elements.type == "text") { AForm.elements.value = ''; } else if (AForm.elements.type == "textarea") { AForm.elements.value = ''; } else if (AForm.elements.type == "select-one") { AForm.elements.selectedIndex = 0; } else if (AForm.elements.type == "select-multiple") { AForm.elements.selectedIndex = -1; } } return true; }
Listing 7.
Funkcja czyszcząca zawartość formularza.
Funkcję clearForm() wywołujemy po naciśnięciu
przycisku ogólnego przeznaczenia
(element INPUT typu button;
posiada on zdarzenie onclick bez żadnej
predefiniowanej procedury obsługi).
<INPUT type="button" value="Wyczyść" onclick="return clearForm(this.form);">
Wywołując funkcję clearForm()
przekazujemy jako parametr obiekt this.form
będący referencją do formularza zawierającego przycisk
(zmienna this oznacza przycisk; każda kontrolka
formularza zawiera pole form
wskazujące formularz, zawierający daną kontrolkę).
Przykładowy formularz czyszczony opisaną metodą jest przedstawiony na rysunku 3.
Rys. 3.
Formularz posiadający przyciski Wyczyść oraz Resetuj.
Modyfikowanie tekstu wprowadzanego w polu INPUT
Nieco innym podejściem do problemu walidacji formularza jest modyfikacja
wartości wprowadzanych przez użytkownika.
Możemy usunąć niepożądane znaki, czy zmienić wielkość liter.
Do zmiany wielkości liter tekstu wprowadzanego przez użytkownika w trakcie
pisania stosujemy metodę onkeyup.
W obsłudze zdarzenia wywołujemy metodę toLowerCase(),
przypisując otrzymaną wartość do pola value:
<INPUT name="proba" onkeyup="javascript:this.value=this.value.toLowerCase();">
Stosując funkcję upperCaseField()
o kodzie:
function upperCaseField(AField) { AField.value = AField.value.toUpperCase(); }
kod HTML pola INPUT przyjmie postać:
<INPUT name="proba" onkeyup="upperCaseField(this);">
Maskowanie klawiszy
Jeszcze inne podejście do zapewnienia poprawności danych pochodzących z formularza
polega na wymuszeniu konkretnych napisów przez zablokowanie części klawiszy.
Jeśli wprowadzane pole ma zawierać kwotę dotacji (wprowadzaną przez użytkownika),
to zakres dostępnych znaków możemy ograniczyć do cyfr oraz ewentualnie
znaków kropki, przecinka czy spacji.
Podobnie, nazwa konta użytkownika zazwyczaj może zawierać litery, cyfry
oraz kilka dodatkowych znaków.
Do zablokowania klawiszy wewnątrz pola tekstowego stosujemy zdarzenie
onkeypress.
Zdarzenie to jest wywoływane ilekroć użytkownik naciśnie dowolny z klawiszy klawiatury,
gdy kursor znajduje się wewnątrz danego pola tekstowego.
Do obsługi zdarzenia wykorzystujemy funkcję maskujKlawisze()
przedstawioną na listingu 8.
Funkcja ta posiada dwa parametry:
zdarzenie event oraz napis zawierający dozwolone litery.
function maskujKlawisze(AEvent, AMaska) { if (window.Event) { kodKlawisza = AEvent.which; } else { kodKlawisza = AEvent.keyCode; }
if (kodKlawisza == 13) { return true; // Enter };
if (kodKlawisza == 0) { return true; // klawisze steruj±ce };
klawisz = String.fromCharCode(kodKlawisza);
if (AMaska.indexOf(klawisz) == -1) { return false; } else { return true; } }
Listing 8.
Funkcja maskująca klawisze.
Jeśli dostępnymi literami mają być cyfry 0, 9, 1 oraz 2, wówczas
funkcję maskujKlawisze() wywołujemy następująco:
<INPUT name="liczba" onkeypress="return maskujKlawisze(event, '0912');">
Natomiast w przypadku, gdy dozwolone są znaki ze zbioru
[abcXYZ], wywołanie ma postać:
<INPUT name="wyraz" onkeypress="return maskujKlawisze(event, 'abcXYZ');">
Pola tekstowe z podpowiedziami
Nieco innym rodzajem ułatwień, udostępnianych przez JavaScript,
są pola tekstowe zawierające podpowiedzi.
Pole takie, przedstawione na rysunku 4, zawiera tekst
Szukaj w Internecie.
Po umieszczeniu kursora wewnątrz pola, tekst znika.
Rys. 4.
Pole tekstowe z podpowiedzią „Szukaj w Internecie”. Podpowiedź znika po umieszczeniu kursora w polu.
Skrypt taki wykorzystuje zdarzenie onfocus,
które jest generowane ilekroć kontrolka staje się aktywna
(czyli otrzymuje kursor).
Treść podpowiedzi jest ustalana jako wartość atrybutu value,
zaś obsługę zdarzenia onfocus
realizuje funkcja czyszSzukaj():
<INPUT name="fszukaj" value="Szukaj w internecie" onfocus="return czyscSzukaj(this);">
Wewnątrz funkcji czyscSzukaj()
sprawdzamy czy pole zawiera tekst podpowiedzi i jeśli tak,
do pola wprowadzamy napis pusty:
function czyscSzukaj(AInput) { if (AInput.value == 'Szukaj w internecie') { AInput.value = ''; } return true; }
Automatyczne wysyłanie formularza
Ostatni z przykładów demonstruje,
w jaki sposób automatycznie wysłać formularz,
gdy została wybrana jedna z jego opcji.
Wysłanie jest automatyczne w tym sensie, że nie wymaga naciśnięcia
przycisku Wyślij.
Formularz taki nie musi w ogóle zawierać przycisku Wyślij,
dzięki czemu zajmuje nieco mniej miejsca w układzie witryny.
W przeglądarce wyświetlana jest lista rozwijana. Wybranie dowolnej
opcji powoduje wysłanie formularza.
W odniesieniu do list rozwijanych, należy wykorzystać
zdarzenie onchange.
Kodem obsługi zdarzenia jest wywołanie metody submit()
formularza zawierającego listę wyboru
(tj. obiektu dostępnego jako this.form):
<SELECT name="dzien" onchange="this.form.submit();"> ... </SELECT>
Sztuczkę taka możemy również zastosować w odniesieniu do innych kontrolek.
Na przykład wykluczające pole wyboru posiada zdarzenie onclick,
którego obsługa może powodować automatyczne wysłanie formularza po
zaznaczeniu jednej z opcji:
<INPUT type="radio" name="fodp" onclick="this.form.submit();">
|