Lomakkeiden käsittely esteettömästi, tekniikkana CGI

Tässä artikkelissa kerrotaan, miten verkkosivustoon toteutetaan lomaketta käyttävä toiminto CGI-tekniikalla siten, että se toimii kaikenlaisissa käyttötilanteissa. Erityisesti kiinnitetään huomiota siihen, että käyttäjän saama palaute on selkeää ja myös ääneen luettuna helposti ymmärrettävä.

Tarkemmin sanoen tekniikkana käytetään Perl-kielellä kirjoitettuja ohjelmia, jotka on asennettu toimimaan CGI-skripteinä. Jos palvelimessa käytettävä tekniikka on jokin muu, esimerkiksi ASP tai PHP, tässä kuvattavat menettelyt eivät sovellu sellaisinaan, mutta esitetyistä yleisistä periaatteista on silti hyötyä.

Lukijan oletetaan tuntevan HTML-lomakkeiden, Perl-kielen ja CGI:n käytön perusteet taikka opiskelevan niitä rinnan tämän aineiston kanssa. Näistä aiheista löytyy tietoja esimerkiksi seuraavien sivujen kautta: WWW-lomakkeet, Suomenkielistä aineistoa Perl-kielestä Webissä ja Web-julkaisemisen oppaan kohta Palvelinskriptit (server-side scripting).

Ensimmäinen tavoite: lomake, jonka voi täyttää vaikka silmät kiinni

Yksi tavoite on, että lomakkeen voi täyttää sananmukaisesti silmät kiinni. Tämä on vain osa yleistä tavoitetta: lomake tulisi voida täyttää erilaisissa käyttötilanteissa ja -muodoissa. Tähän sisältyy myös esimerkiksi se, että lomakkeen voi täyttää myös kokonaan ilman hiirtä tai vaikkapa puhumalla, sikäli kuin käyttäjän laite ja ohjelmisto tätä tukevat.

Alla on esimerkki lomakkeen osasta, joka ei kovin hyvin täytä tätä vaatimusta:

Tämän voisi selain esittää ääneen esimerkiksi näin: "Lomake alkaa. Sukunimi etunimi synt asiakasnumero. Kirjoita teksti." Käyttäjän kirjoitettua ensimmäisen syöttötiedon kuuluisi seuraavaksi uusi kehote: "Kirjoita teksti". Kirjoittaminen käy hankalaksi, jos kenttiä on paljon, koska käyttäjän pitää muistaa tietojen järjestys.

Harjoitustehtävä: Millainen olisi vaihtoehto, joka toimisi paremmin ääniesityksessä? Mitä etuja tai haittoja siitä olisi näkyvässä esityksessä?

Harjoitustehtävä: Mene Googlen sivulle, jolla monipuolinen hakutoiminto ("advanced search", suomenkielisessä versiossa "lisähaku"); osoite on <http://www.google.com/advanced_search>. Siirrä hiiri syrjään niin, ettet pääse siihen käsiksi. Tee haku, joka etsii ruotsinkielisiä sivuja .fi-domainista hakusanana kiva. Millaisia vaikeuksia hiirettömyys aiheutti?

Aihetta käsitellään jäljempänä kohdassa Esteettömän lomakkeen tekeminen. Lomakkeen täyttämisen ja lähettämisen sujuvuuden lisäksi on tärkeää, millaisen vastauksen käyttäjä saa, kun hän on lähettänyt lomakkeen. Tätä aihetta on yleensä käsitelty melko vähän, yllättävän vähän.

Toinen tavoite: vastaus, joka menee suoraan asiaan

Jos kyse on esimerkiksi hakutoiminnosta, jossa käyttäjä on antanut hakusanan ja napsauttanut Hae-painiketta, hänen saamansa vastauksen tulisi alkaa olennaisilla tiedoilla. Hyvin olennaista on, montako osumaa kaikkiaan löytyi, koska varsin usein osumien määrästä voidaan heti päätellä, onko hakua syytä tarkentaa tai muuten muuttaa, suunnilleen seuraavaan tapaan:

Haku sanalla "kissa" tuotti 47 900 osumaa: - -

Tällaisen tiedon olisi hyvä olla heti alussa ja mielellään myös korostettuna - ei siis siihen tapaan, kuin eräs monella muulla tavalla hyvä hakutoiminto aloittaa vastauksensa:

Siirry Googlen kotisivulle
   
Lisähaku    Asetukset    Kielivalinnat    Hakuvihjeitä 

Etsi WWW:stä Etsi kielellä suomi 
 Webbi 
 Kuvat 
 Keskusteluryhmät 
 Hakemisto 

Jos edellä oleva luettaisiin puhesyntetisaattorin avulla, esitys alkaisi tähän tapaan: "siirry googlen kotisivulle lisähaku asetukset kielivalinnat hakuvihjeitä kissa syöttökenttä google-haku valintanappi etsi vee vee veestä valintanappi etsi kielellä suomi vebbi kuvat keskusteluryhmät hakemisto". Vasta tämän jälkeen käyttäjä kuulisi, mikä oli haun tulos. Lisäksi sivulla näkyvästä esityksestä monen on hankala löytää olennaisin tieto, ellei se ole alussa.

Kolmas tavoite: palautetta käyttäjälle

Käyttäjälle tulee antaa riittävästi, mutta ei liikaa palautetta siitä, mitä tapahtui. Palautteen tulee olla helposti ymmärrettävässä muodossa, ei koodattuna eikä ammattikielellä.

Edellä sanottu koskee ensiksikin virhetilanteita. Jos käyttäjä on kirjoittanut vuosiluvun tilalle "tänä vuonna", hänen tulisi saada sentapainen virheilmoitus kuin "ilmoita vuosi nelinumeroisella vuosiluvulla", eikä siis esimerkiksi "digit expected", kuten helposti käy, jos lomakkeen käsittelyn koodaaja käyttää valmiita rutiineita ilman, että hän ottaa huomioon niiden vaikutuksen käyttöliittymään.

Myös normaalitilanteissa käyttäjän tulisi saada tietoa siitä, että kaikki menee hyvin, ja myös riittävästi tietoa esimerkiksi tallennettavaksi myöhempää käyttöä varten. Jos kyse on palautelomakkeesta, lomakkeen käsittelyn tulisi antaa vastaukseksi vaikkapa sivu, joka kertoo, milloin palaute on lähtenyt ja joka sisältää kopion käyttäjän kirjoittamasta tekstistä. On sitten käyttäjän ratkaistavissa, haluaako hän tulostaa sivun itselleen, tallentaa sen levylle, lähettää tiedoksi jonnekin tai muuta sellaista.

Jos kyse on esimerkiksi ilmoittautumis- tai tilauslomakkeesta, saatavan palautteen tulisi selvästi kertoa tapahtumista luomatta vääriä mielikuvia. Usein lomakkeen käsittelevä koodi vain tallentaa tiedot, jotka ihminen sitten myöhemmin käsittelee. Ilmoittautumista ei ole ehkä hyväksytty tai tilatun tavaran saatavuutta ei kenties ole mitenkään varmistettu. Saattaa olla tarpeen sanoa tämä erikseen, selvyyden vuoksi sekä myönteisesti että kielteisesti esimerkiksi seuraavaan tapaan: "Tämä on automaattinen vastaus tilaukseenne. Tilauksenne on tallentunut järjestelmäämme; se tullaan käsittelemään ja teille tullaan ilmoittamaan, voidaanko tuote tai tuotteet toimittaa ja milloin. Tämä ei ole tilausvahvistus, vaan vain ilmoitus siitä, että tilauksenne on nyt odottamassa käsittelyä."

Lomakkeen luonnin perusteet

On mahdollista kirjoittaa lomake (form-elementti) suoraan HTML-dokumenttiin jollakin editorilla tai sivunteko-ohjelmalla. Yleensä on kuitenkin parempi tuottaa lomake (ja koko sivu, jolla se on) samalla ohjelmalla, joka käsittelee lomakedatan. Tästä on muun muassa se etu, että tällöin voidaan toteuttaa helposti se, että käyttäjän saama vastaus sisältää uuden kopion lomakkeesta esimerkiksi uutta, tarkennettua hakua varten. Näin toimivat muun muassa useimmat yleiset hakupalvelut. Kätevimmin tämä käy Perlin CGI.pm-modulilla, jota jatkossa käytämme.

Seuraava alkeisesimerkki on Perl-ohjelma, joka CGI-skriptinä kutsuttuna tulostaa syötteenä annettujen lukujen tulon, jos syötteitä on. Joka tapauksessa ohjelma tulostaa HTML-lomakkeen, jolla voi antaa syötteenä kaksi lukua ja lähettää ne saman ohjelman käsiteltäviksi. Tämä voi olla aluksi käsitteellisesti hämäävää, mutta kyse on sekä näppärästä että hyödyllisestä menettelystä.

#!/usr/local/gnu/bin/perl
use CGI qw(:standard);
print header, start_html(-title=>'Kertolasku',-lang=>'fi'),
  h1('Kertolasku');
$eka = param('eka');
$toka = param('toka');
if($eka && $toka) {
  $tulo = $eka * $toka;
  print p("Lukujen $eka ja $toka tulo on $tulo.");
  print hr, start_form(-method=>'get'),
    p('Voit tehdä uuden kertolaskun:'),
    div(defaults('Tyhjennä lomakkeen kentät')); }
else {
  print start_form(-method=>'get'); }
print
  div('Tällä lomakkeella voit laskea kahden luvun tulon.'),
  div('<label for="k1">1. luku:</label>',
       textfield(-name=>'eka',-id=>'k1')),
  div('<label for="k2">2. luku:</label>',
       textfield(-name=>'toka',-id=>'k2')),
  div(submit(-value => 'Laske tulo')),
end_form,
end_html;
Selityksiä:

Harjoitustehtävä: Selvitä, miten voit asentaa käyttämääsi palvelimeen Perl-ohjelman CGI-skriptiksi, ja tarkista, että CGI.pm on tällöin käytettävissä. Asenna sitten yllä oleva ohjelma ja kokeile sitä. Huomaa, että kyseinen selvittely ei aina ole ihan helppoa. Jos tämä ei onnistu, kokeile kyseistä skriptiä valmiiksi asennettuna osoitteessa <http://www.cs.tut.fi/cgi-bin/run/~jkorpela/kerro.cgi>. Joka tapauksessa kokeile lomakkeen käyttöä myös ilman hiirtä.

Virheiden käsittely

Ihmiset tekevät virheitä, joskus hyvinkin paljon. Esimerkiksi lukihäiriöinen kirjoittaa hakusanoja väärin, kättään vaikeasti liikuttava saattaa napsauttaa väärää painiketta ja hätäisesti päätöksiä tekevä lähettää tiedot, vaikka kaikkia välttämättömiä kenttiä ei ole täytetty.

Hyvässä lomakkeenkäsittelyssä on sekä selaimessa tapahtuvia tarkistuksia että palvelimessa tapahtuvia tarkistuksia, yleensä niin, että sama asia tarkistetaan kahteen kertaan. Selaimessa tapahtuva tarkistus on hyödyksi, koska se antaa käyttäjälle nopean palautteen, jopa niin, että heti kirjoitettuaan vaikkapa sanan johonkin kenttään hän saa tiedon, että pitää kirjoittaa luku. Käytännössä kyse on JavaScript-koodista, joka liitetään sopivalla tavalla HTML-dokumenttiin. Palvelimessa tapahtuva tarkistus taas on varmistus, koska on monia syitä, joiden takia selaimessa tapahtuva tarkistus voi jäädä suorittamatta. Palvelimessa tapahtuva tarkistus on tärkeämpi yleisen toimivuuden ja turvallisuuden takia. Lisäksi siihen voi sisältyä sellaisia asioita, joita olisi mahdoton tehdä selaimessa, kuten tietokantoihin liittyvät tarkistukset.

Jos esimerkiksi testaamme edellä esitettyä lomaketta tekemällä kertolaskua tarpeeksi monta kertaa, huomaamme, että voimme kirjoittaa kenttiin vaikkapa kirjaimet a ja b ja saada mielettömän tuloksen "Lukujen a ja b tulo on 0".

Harjoitustehtävä: Miten kertolaskuohjelmaa pitäisi kehittää, jotta se asianmukaisesti havaitsisi ja käsittelisi virhetilanteet kuten sen, että syöttötiedot eivät ole lukuja lainkaan? Perlissä on useita erilaisia tapoja tarkistaa, onko muuttujan arvo luku. Tällöin joudutaan määrittelemään tarkemmin, mitä luku tässä tarkoittaa. Yksi tapa on seuraavanlainen testi:
if($foo == 0 && $foo ne "0") ...
(Tämä perustuu siihen, että operaattori == tekee numeerisen vertailun: jos $foo:n arvo on ei-numeerinen, tulos on nolla. Testin toinen osa huolehtii siitä, että tämä erotetaan tapauksesta, jossa arvo on nimenomaan  0.) Halutessasi voit tarkastella asiaa myös vain periaatteellisesti: oletetaan, että sopivat testit ovat käytettävissä. Miten ohjelman tulisi ilmoittaa virheistä, jotta on käyttäjäkin ymmärtää, että tällä kertaa ei tullutkaan tulosta vaan virheilmoitus? Miten muotoilisit ilmoitukset ja miten auttaisit käyttäjää jatkamaan virhetilanteen jälkeen?

Todelliset lomakkeet ovat usein melko laajoja, eli niissä on paljon kenttiä. Tällöin ei riitä, että kullekin kentälle on tarkistukset, vaan lisäksi kokonaisuuden tulee olla helposti hahmotettavissa. Lomaketta lähetettäessä (selaimessa) tai lomakkeen lähettämisen jälkeen (palvelimessa) tarkistuksen suorittava koodi saattaa esimerkiksi havaita, että kahden kentän arvot muodostavat loogisesti mahdottoman yhdistelmän. Tällöin on olennaista kertoa,

Esteettömän lomakkeen tekeminen

Edellä on käsitelty sitä, miten lomakkeilla lähetettyjen tietojen käsittely saadaan esteettömäksi, ja ennen muuta sitä, miten käyttäjän saamat vastaukset ovat käyttökelpoisia kaikille. Myös itse lomakkeen täyttäminen voi olla ongelmallista. Asiaintilan parantamiseksi lomakkeisiin tarvitaan erityisiä esteettömyyspiirteitä hyvän ja loogisen yleisen rakenteen lisäksi.

Edellä esitetyssä esimerkissä oli jo yksi keskeinen esteettömyyspiirre: kukin syöttökenttä on omalla rivillään, jolla on myös sen selite, ja nämä on liitetty toisiinsa label-merkkauksella. Selitteen on syytä olla ennen tekstinsyöttökenttää. Jos taas kyseessä on valintanappi (radio buttons, input type="radio") tai asetusnappi (input type="checkbox") eli valintaruutu, on syytä noudattaa yleistä tapaa kirjoittaa selite sen jälkeen. Näiden kenttien yhteydessä on label-merkkauksesta erityinen etu, koska sen ansiosta käyttäjä voi napsauttaa myös selitetekstiä tehdäkseen valinnan. Tämä on olennaista, koska napit ovat yleensä aika pieniä ja siksi niihin osuminen vaatii tarkkaa motoriikkaa. Seuraavassa on asetusnapista ja selitteestä esimerkki, jonka avulla voit testata, tukeeko oma selaimesi tässä kuvattua piirrettä eli voiko asetuksen muuttaa myös tekstiä klikkaamalla:

Käytetty merkkaus on:
<div><input type="checkbox" name="lounas" id="chk"><label for="chk">Haluan ilmaisen lounaan</label></div>

Muita erityisiä esteettömyysperiaatteita ja niiden toteutustapoja CGI.pm:ää käytettäessä on lueteltu alla.
  1. Pyri tekemään lomake omaksi sivukseen, ellei kyseessä ole hyvin yksinkertainen lomake kuten "hae tästä sivustosta" -lomake. Oma sivu auttaa keskittymään lomakkeen täyttämiseen.
  2. Kirjoita tarvittavat ohjeet ennen syöttökenttiä. Tämä on olennaista puhesynteesiä käyttäville mutta myös muille. Moni ihminen lukee tekstiä lopusta alkuun, vaikka loppupuolella olisi korostettujakin huomautuksia.
  3. Jos kuitenkin ohjeita olisi paljon (useita virkkeitä), yleensä on parempi sijoittaa ne linkin taakse. Tällöin lomakkeen alussa siis on vain viittaus varsinaisiin ohjeisiin, ja itse lomakkeessa on vain lyhyet kenttien selitykset. Tämä koskee varsinkin sellaisia lomakkeita, joita käytetään toistuvasti, sillä ei ole hauskaa aina kuulla samoja ohjeita aluksi. Jos kuitenkin on jotain erityisen tärkeää varoitettavaa, se täytyy sanoa itse lomakesivulla, koska ihmiset eivät useinkaan katso erillisiä ohjeita.
  4. Sijoita lähetyspainike (submit button) viimeiseksi ja anna sille lomakkeen lähettämisen merkitystä kuvaava nimi. CGI.pm:llä tämä voidaan tehdä seuraavaan tapaan: submit(-value=>'Hae') tai submit(-value=>'Ilmoittaudu').
  5. Älä laita lomakkeeseen tyhjennyspainiketta (reset button). Siitä on lähes aina pelkkää harmia, kun käyttäjä lomakkeen huolella täytettyään vahingossa painaa väärää nappia. Sen sijaan joissakin tapauksissa voi olla aiheellista sijoittaa lomakkeen alkuun, kauas lähetyspainikkeesta, edellä kuvattu alustuskenttä defaults-funktiolla.

Harjoitustehtävä: Hahmottele, miten aiemmin tarkasteltua Googlen monipuolista hakutoimintoa voisi kehittää edellä esitettyjen periaatteiden mukaisesti. Voit myös tehdä vastaavan hahmottelun ja ehkä toteutusluonnoksenkin jollekin muulle suhteellisen isolle lomakkeelle.

Lisätietoja

Lisätietoja lomakkeiden käytön tekemisestä esteettömäksi on Tieken Esteettömyysoppaassa kohdassa Lomakkeet, jossa on myös linkkejä englanninkieliseen lisäaineistoon.

CGI.pm:ää käsittelee johdattelevasti The Fool's Guide to CGI.pm, the Perl module for CGI scripting ja yksityiskohtaisesti alkuperäisdokumentaatio CGI.pm - a Perl5 CGI Library.

Virheilmoitusten tekemistä ymmärrettäviksi käsittelee Error Message Guidelines .

Jukka K. Korpela (jkorpela@cs.tut.fi)

Kurssimateriaalin kommentointi

Kommenttien lähettämistoiminto on poistettu käytöstä suuren roskapostimäärän vuoksi 21.6.2007. Oikeita palautteita tuli reilusti alle promillen luokkaa kaikista viesteistä :-( Halutessasi voit lähettää palautteesi suoraan Essin toteuttajille .

Muita artikkeleita aiheesta:
Seuraa polkua:
Edellinen: WWW-lomakkeiden toteuttaminen
Seuraava: Essiin liittyvät ydinlinkit