[Alku]
Testaa CSS-oppaan navigoinnin toimivuutta!
 
   
 Etsi sivuiltani: [Apua]

I Miten luoda dynaamisia valikoita

Luontosivut

Aiheet

Tämä sivu on jaettu jaksoihin, jotka sisältävät seuraavia aiheita:

Sisältö yhtenä isona sivuna

Yleistä

Tämä sivu antaa vihjeitä monitasoisten dynaamisten valikoiden luomiseen. Ulkoasu-jaksossa on myös vihjeitä, joita voi soveltaa myös staattisiin valikoihin.

Miten luoda dynaamisia valikoita toimivat aluksi vain tietyissä Netscape ja MS IE -selaimissaepästandardilla JavaScript-koodauksella, jolle annettiin nimitys DHMTL (Dynamic Hyper Text Markup Language). Tuon ajan jälkeen W3C on standardisoinut mm. dynaamisten muutosten aikaansaavan koodauksen DOM-spesifikaatioissa (Document Object Model). Standardi koodauskieli on nimeltään ECMAScript ja JavaScript on standardia siinä määrin kun se noudattaa ECMAScript-standardeja.

ECMA: ECMAScript language binding; W3C: Document Object Model (DOM) Level 1 Specification (Version 1.0, W3C Recommendation 1 October, 1998), Document Object Model (DOM) Level 2 Core Specification (Version 1.0, W3C Recommendation 13 November, 2000).

Uusimmat selaimet tukevat DOMia vaihtelevassa määrin. Parhaiten standardit menetelmät on tuettu uusimmissa MS IE, Mozilla Gecko (esim. Netscape 6.1+) ja Opera 7.x+ -selaimissa. Myös Opera 4.x-6.x -selaimissa on kokeellinen DOM-tuki. Käyttämäni JavaScript toimii myös Opera 4.x:ssä, mutta kokemukseni mukaan dynaamisten valikoiden yleistoimivuus on em. selaimissa heikko. Valikot toimivat sangen hyvin Opera 5.x-6.x -selaimissa, mutta kaikki DOM-pohjaiset valikot eivät kuitenkaan toimi Opera 4.x-6.x -selaimissa. Ne tukevat myös joitakin MS IE:n laajennuksia.

Koska on täysin mahdollista luoda dynaamisia valikoita, jotka toimivat ainakin MS IE 4.0+ Windows, MS IE 5.x+ Mac, Netscape 4.x ja Opera 5.x+ selaimissa, keskityn tällä sivulla opastamaan sellaisten valikoiden luomista, jotka toimivat kaikissa em. selaimissa. Valikot saattavat toimia myös vanhemmissa MS IE Mac -selaimissa, mutta minulla ei ole tietoa valikoiden toimivuudesta näissä selaimissa.

Pelkästään Netscape 4.x huomioiva koodi ei toimi Netscape 6.x -selaimissa, sillä Netscape 4.x -selaimet käyttävät dynaamisissa valikoissa epästandardia metodia document.layers(), jota Mozilla Gecko -selaimet eivät tue. Ne eivät ei tue myöskään Netscape 4.x:n tukemia LAYER ja ILAYER elementtejä (sen sijaan niiden kanssa voi käyttää elementtiä IFRAME, jota periaatteessa voisi käyttää dynaamisissa valikoissa, mutta jonka käyttö on sangen ongelmallista). Valikot pitäisi rakentaa käyttäen metodia document.getElementById() (ehkä myös getDocumentElement() olisi joissakin tilanteissa mahdollinen metodi). Netscape-selaimissa toimivien skriptien pitäisi siten sisältää sekä Netscape 4.x että Netscape 6.x -selainten vaatimat metodit.

Mozilla org.:What have *YOU* done for web standards today? Mozilla new layout engine
Are your JavaScript and CGIs ready for Nav5, IE5, and HTTP 1.1 CONTENT_TYPE? Get the latest info from Erick Krock.
Jos sinulla kysyttävää, ennen kuin kirjoitat Eric Krockille, katso ensin vastauksia.

Dynaamisten valikoiden luomisesta selviää helpoiten eräillä kaupallisilla ohjelmilla. DHTML Menu Builder luo automaattisesti eri selainten tarvitsemat HTML-rakenteet ja CSS:n. Ohjelman vanhemmat versiot luovat epäkelpoa CSS:ää (uudemmat standardien mukaista). Jos CSS ei ole kelvollista, valikot toimivat joissakin selaimissa vain sellaisilla HTML dokumenttityypeillä, joissa selain ei toimi ns. standard(-compliant) -moodissa[S].

xFX JumpStart: DHTML Menu Builder.

Mikäli tunnet yhtään PHP:tä, olen yrittänyt tehdä eräälle toiselle sivulle mallin, jossa PHP:n avulla valikon päivittäminen[S] on suhteellisen helppoa. Tällä sivulla käsitellyt mallit ovat staattista HTML-koodia.

Tarkoitukseen on saatavissa ilmaisiakin skriptejä. Käyttämäni skripti näyttää olevan alun perin sangen uuden Macromedia Dreamweaverin tuottamaa (saamani s-postin mukaan skriptiä on käytetty versiosta 4.01 lähtien; skripti ei tosin ole sivuillani alkuperäisessä muodossa). Sen pääfunktion (MM_showHideLayers(), versio 3.0) hyödyntämistä opetetaan monilla Web-sivustoilla, esim. TecsOfTheWeb.Com. Vaikka perusskripti on erään kaupallisen sovelluksen tuottamaa, se on vapaasti käytettävissä.

Macromedia;TecsOfTheWeb.Com: Using and Manipulating Dropdown Windows.

Suomalainen tv-kanava Nelonen käyttää samaa skriptiä yksitasoisissa alivalikoissa. Sivusto käyttää kuitenkin Netscape 4.x -selaimille hitaita Java-appletteja. Antamalla hakusanaksi käyttämäni pääfunktion nimen, netistä löytyy paljon samaa funktiota käyttäviä sivustoja. Toinen esimerkki hyvin Operassa (ja todennäköisesti kaikissa muissakin uusissa selaimissa) toimiva valikko on myös Yomi Median sivustolla (se käyttää eri JavaScript-koodausta, mutta toimintaperiaate on samankaltainen).

Nelonen, Yomi Media.

Netistä löytyy myös on skriptejä, jotka toimivat Netscape 4.x ja vanhemmissa MS IE -selaimissa, mutta eivät Opera 4.x-6.x ja Mozilla Gecko -selaimissa (Opera 7.x tukee MS IE:n epästandardia DHTML:ää, joten siinä toimii ainakin osa vanhoille MS IE -selaimille toimivista valikoista). Eräät MS Frontpage versiot luovat valikoita, jotka eivät toimi kaikissa DHTML/DOM tukevissa selaimissa. Jotkut skriptit voivat toimia uusissa MS IE ja Netscape -selaimissa, mutta eivät vanhemmissa MS IE ja Netscape -selaimissa. Alla on Web-osoite, jolla opetetaan dynaamisia valikoita, jotka toimivat useimmissa DOM1 tukevissa selaimissa (MS IE 5.x+ Windows, Opera 4.x+ ja sangen uudet Mozilla Gecko -selaimet), mutta eivät vanhemmissa MS IE ja Netscape -selaimissa.

CodeStyle: DOM1 Visibility menus

Myös MS IE 5.0 Mac tukee DOM1:tä. Webreview kirjoittaa selaimen tuesta seuraavasti:

A good portion of DOM1 is supported in IE 5 for the Mac (chunks of DOM1 core are missing). However, the DOM support in Mac and Windows IE 5 is not consistent. This code is not cross-platform, and the Macintosh engine, while perhaps better at implementing DOM 1.0, is not consistent with IE 5 for Windows in all areas.
Webreview.

Käyttämäni perusskriptin etu on siinä, että skripti toimii kaikissa selaimissa, jotka ylipäätänsä tukevat dynaamisia valikoita. Siinä on vaihtoehdot joko epästandardin DHTML:n tai standardin DOMin mukaan toimiville selaimille. Tällä sivulla olevat ohjeet perustuvat yhden valmiin skriptin käyttämiseen (siihen ei tarvitse välttämättä koskea lainkaan).

Selaimissa on kuitenkin erilaisia ongelmia, jolloin optimaalista ratkaisua on vaikea saavuttaa. Pääpaino on uusimmissa selaimissa, mikäli kaikkia selaimia tyydyttävää ratkaisua ei löydy. On periaatteessa mahdollista - mutta ison työn takana - luoda käyttämäni skriptin avulla "käsityönä" kauniin näköisiä useimmissa selaimissa toimivia dynaamisia valikoita. Jokainen voi itse päättää, mitä selainta hän aikoo tukea. Vanhimmille DTHML:ää tukeville selaimille saattaa olla mielekkäämpää antaa staattiset valikot. Selvitän erillissivulla[S], kuinka itse käyttämäni dynaamiset valikot toimivat eri selaimissa.

Mikäli käytetään jotain muuta koodia, dynaamisten muutosten täytyy perustua ominaisuuden visibility arvon vaihtamiseen, sillä Operassa ei toimi ominaisuuden display dynaamiset muutokset. Mikäli käytät jälkimmäistä tapaa, varmista edes se, että Opera saa käyttöönsä edes sen verran linkkejä, että navigoiminen on mahdollista ilman dynaamisia valikoita.

DHTML/DOM-valikot voi periaatteessa korvata joissakin tapauksissa myös käyttämällä dynaamisia näennäisluokkia (:hover, :active ja :focus) ja IFRAME elementtejä. Tein sivuja, joissa on näin luotuja kokeellisia alivalikoita[S]. Testeissäni systeemit toimivat vain MS IE 5.5+ Windows, Netsape 6.1+ (pitäisi toimia myös vastaavissa muissa Mozilla Gecko -selaimissa), mutta eivät millään Operalla (tosin toimii melkein Opera 7.0 Beta 1:ssä). DHTML/DOM:in tavoin IFRAME ei toimi kaikissa selaimissa, minkä vuoksi selaimille olisi annettava mahdollisuus navigoida sivustoa myös ilman IFRAME-tukea. Koska ratkaisun toimivuusaste on heikko, en suosittele sitä kenellekään. Ainoa ratkaisun etu on siinä, että se toimii myös silloin, kun JavaScript-tuki on pois päältä. Pelkän CSS:n avulla voi kuitenkin luoda vain yksitasoisia dynaamisia valikoita kun DHTML/DOM valikot voivat niin monitasoisia kuin kussakin tilanteessa on tarpeellista.

[Alku]

Ongelmatilanteiden ratkaisut

Koska DHTML/DOM1 toimii eri asteisesti selaimissa, mielestäni DHTML/DOM:iin perustuvat valikot tulisi suunnitella siten, että sivut toimivat myös sellaisissa selaimissa, jotka eivät tue DHTML/DOM-skriptejä. Sivujen olisi syytä toimia myös tilanteissa, joissa JavaScript on poissa päältä. Olen havainnut tilanteita, joissa sivujen navigointia ei ole olemassa ilman sopivaa JavaScript-tukea. Syynä tähän on kaksi mahdollisuutta. Joko linkit luodaan "lennosta" JavaSript-koodauksella tai linkkien oletusarvo on se, että ne on piilotettu (nillä on oletuksena joko ominaisuus visibility:hidden or display:none). Pidän kumpaakin edellä mainittua ratkaisua huonona. Linkit saisi näkyviin, jos piilotus toteutettaisiin niin, että sivulle saavuttaessa kaikki valikot piilotetaan BODY-elementille annetun onload-attribuutin avulla. Tässä tapauksessa linkit olivat näkyvillä ilman JavaScript-tukea. Tämä ratkaisu ei kuitenkaan toimi, sillä dynaamisissa valikoissa linkit menevät muun sisällön ja mahdollisesti myös osittain tai kokonaan toistensa päälle.

Mielestäni parempia ratkaisuja ovat seuraavat:

  1. Päälinkit toimivat kaikissa selaimissa ja niiden kautta pääsee sivuille, joissa on jatkolinkit. Tässä ratkaisussa dynaamiset valikot ovat vain alivalikkoja. Tässä tapauksessa on epäolennaista luodaanko alivalikkojen linkit JavaScript-koodauksella vai ovatko linkit aina olemassa itse sivulla, mutta JavaScript piilottaa/paljastaa ne tarvittaessa. Sekään ei haittaa, vaikka osa linkeistä olisi piilotettuna, kun JavaScript on pois päältä.

    Selainkohtaisia huomautuksia:

    1. Ei ole mitenkään mahdollista ratkaista kaikkia JavaScript koodaukseen tai servereihin liittyviä ongelmia, mutta jos esitysasu ei ole riippuvainen siitä, onko JavaScript-tuki päällä vai pois päältä sivuilla vierailija ei ihmettele, miksi sivun ulkoasu muuttui äkisti. Tässä mielessä tämä vaihtoehto on järkevin.

  2. Valikoihin liittyvät LINK elementit tuotetaan skripteillä. CSS voidaan helposti räätälöidä eri selaimille sopivaksi. Alla on joitakin esimerkkejä mahdollista toteutustavoista:

    <script language="JavaScript" type="text/javascript">
    <!--
    function linkStyle(sStyleFile,sStyleMedia)
    {document.writeln('\<lin'+'k\ rel=\"stylesheet\"\ type=\"text\/css\"\
    href=\"..\/Css\/'+sStyleFile+'\"\ media=\"'+sStyleMedia+'\"\ \/\>');}
    /* Koodin lyhentäminen funktion avulla. Jatkossa tiedostonimi ja mediatyyppi annetaan funktion argumentteina. */

    if (document.layers)
    {linkStyle("layersNetscape4.css","screen");}
    /* Ehto Netscape 4.x -selaimille, jotka eivät tue DOM1:tä, mutta tukevat selainkohtaista DHTML:ää. Netscape 4.x -selaimille attribuutille media ei saa antaa yhtä useampaa arvoa (esim. screen,print). */

    else { /* CSS muille selaimille. Netscape 4.x -selaimilla on vaikeuksia monimutkaisten ehtolauseiden kanssa. On paras antaa sille yksinkertaisimmat mahdolliset ehdot. */
    if (document.getElementById) /* Tämä testaa tukeeko selain erästä DOM1:een kuuluvaa metodia. Ehto koskee kaikkia sellaisia selaimia, jotka tukevat käytetyssä skriptissä DOM1-jaksoa (Windows-käyttöjärjestelmässä sitä tukevat MS IE 5.0+, Opera 4.x+, Netscape 6.x+ ja vastaavat Mozilla -selaimet). */
    {linkStyle("layers.css","screen,projection");} /* Opera tarvitsee mediatyypin projection. Tulevaisuuden PDA-selaimet voivat tarvita myös handheld. */

    else if (document.all)
    {linkStyle("layers.css","screen");}
    /* Ehto kaikille sellaisille MS IE -selaimille, jotka eivät tue DOM1:tä, mutta tukevat selainkohtaista DHTML:ää. Koska käytetty CSS-tiedosto on sama kuin edellisessä testissä, ehto olisi voitu yhdistää edelliseen testiin käyttämällä muotoa (document.getElementById) || (document.all).*/

    else if (!(document.layers) && !(document.all) && !(document.getElementById)) {linkStyle("noLayers.css","screen");} /* Tuntemattomille selaimille, jotka eivät tue selainkohtaista DHTML:ää eivätkä standardia DOM1:tä. Jos ne tukevat CSS:ää, ne saavat staattiset, kerroksettomat linkkitaulukot. Tässä tapauksessa ehdot ovat tarpeettomia, mutta tämä on esimerkki poissulkevien ehtojen käytöstä. */

    else {} /* Lohkon päätös. Tämän kohdan voi jättää pois, mutta on hyvä tapa päättää ehdot tällä tavoin. */
    }
    //-->
    </script>
    <script language="JavaScript" type="text/javascript">
    <!--
    /* Tässä mallissa useimmat selaimet on tunnistettu selainkohtaisiin tietoihin perustuen. */

    function linkStyle(sStyleFile,sStyleMedia)
    {document.writeln('\<lin'+'k\ rel=\"stylesheet\"\ type=\"text\/css\"\
    href=\"..\/Css\/'+sStyleFile+'\"\ media=\"'+sStyleMedia+'\"\ \/\>');}


    var IE4, OP, Gecko; /* On hyvä käytäntö listata yleismuuttujat. */

    IE4 =(((navigator.userAgent.indexOf('MSIE')!=-1) || (navigator.userAgent.indexOf('Internet Explorer')!=-1)) && (navigator.userAgent.indexOf('Mozilla\/4.')!=-1)); /* Koska uudemmat MS IE -selaimet esittäytyvät myös Mozilla/4.0 yhteensopivina tämä tunnistus soveltuu myös uudemmille selaimille. Jotkut MS IE -selaimet käyttävät MSIE asemesta Internet Explorer tunnistusjonoa. */
    OPua = (navigator.userAgent.indexOf('Opera')!=-1); /* Opera-selainten yleistunnistus. */
    op_pos=nua.indexOf('Opera'); /* Hae tietty merkkijono. */
    OPnu=nua.substr((op_pos+6),1);
    OPnu2=nua.substr((op_pos+7),1);
    /* Ensiksi määritellään, mistä kohtaa numeeristen arvojen laskeminen aloitetaan tietyn merkkijonon jälkeen. Numero 1 kertoo kuinka monia digitaaleja käytetään. Joissakin Opera 5.x+ Symbian OS (EPOC) selaimien esittäytymisjonoissa versionumeron edellä voi olla kirjain v, jolloin tarvitaan muotoa (op_pos+7),1. */
    OP=(OPua && ((OPnu>=4) || (OPnu2>=5))); /* Tunnistus Opera 4.x or uudemmille selaimille. Tässä tapauksessa numeerisia arvoja vertaillaan keskenään edellä olleiden muuttujien (OPnu ja Opnu2) avulla. Opera-selaimiamia voitaisiin tunnistaa myös käyttämällä ((navigator.userAgent.indexOf('Opera 5')!=-1) || (navigator.userAgent.indexOf('Opera\/5')!=-1) || (navigator.userAgent.indexOf('Opera\/v5')!=-1) || (navigator.userAgent.indexOf('Opera v5')!=-1)) kaltaisia tunnistusjonoja. Jos esim. Opera 5.12 (Windows) toimisi esittäytymismoodissa Esittäydy: Opera (engl. Identify as Opera) se antaisi tunnistusjonon Opera/5.12 ja muissa esittäytymismoodeissa se antaisi jonon Opera 5.12. Koska dynaamiset valikot toimivat kunnolla vasta 5.x lähtien Opera 4.x olisi mielekästä jättää huomioimatta. */
    Gecko = (navigator.product == ('Gecko')); /* Kaikille Mozilla Gecko perusteisille selaimille tarkoitettu tunnistus. Voidaan käyttää myös saman tyyppistä tunnistusta kuin edellä MS IE selaimille (navigator.userAgent.indexOf('Gecko')!=-1). */

    if (document.layers)
    {linkStyle("layersNetscape4.css","screen");}
    /* Netscape 4.x -selainten dynaamisten valikoiden CSS. Netscape 4.x -selainten tunnistus luomalla tunnistusjonoa koskeva muuttuja ei toimi. */

    else {
    if(IE4||OP)
    {linkStyle("layers.css","screen,projection");}
    /* Dynaamisten valikoiden CSS MS IE 4.0+ ja Opera 4.x+ -selaimille. */

    else if (Gecko)
    {linkStyle("layersGecko.css","screen");}
    /* Kokonaan oma tai täydennetty dynaamisten valikoiden CSS Netscape 6.x+/Mozilla -selaimille. Oman CSS-tiedoston tarve on hyvin pieni. Mikäli omaa CSS:ää ei tarvita, tunnistaminen on mahdollista yhdistää edelliseen ehtoon kirjoittamalla se muotoon (IE4||OP||Gecko). */

    else {}
    //-->
    </script>
    <script language="JavaScript" type="text/javascript">
    <!--
    /* Metodi- ja selaintunnistuksen yhdistelmä. Kun tunnistus perustuu tuettuihin piirteisiin saadaan mahdollisimman laaja tuntemattomien selainten kattavuus. Ainakin ensisijainen tunnistus pitäisi perustua metodien tukemiseen. Vain osa tunnistuksesta tulisi perustua selaimen nimeen tai muihin selainkohtaisiin tietoihin. */

    function linkStyle(sStyleFile,sStyleMedia)
    {document.writeln('\<lin'+'k\ rel=\"stylesheet\"\ type=\"text\/css\"\
    href=\"..\/Css\/'+sStyleFile+'\"\ media=\"'+sStyleMedia+'\"\ \/\>');}


    if (document.getElementById){

    var OP, Gecko;
    OP =(navigator.userAgent.indexOf('Opera')!=-1);
    Gecko = (navigator.userAgent.indexOf('Gecko')!=-1);

    if (OP)
    {...}

    else if (Gecko)
    {...}

    else
    {...}
    }

    else if (document.all)
    {...}

    else {}

    //-->
    </script>

    Selainkohtaisia huomautuksia:

    1. Jos on tarpeen tunnistaa MS IE -selaimet tarkemmin kuin edellä olleissa esimerkeissä, se voidaan tehdä esim. käyttämällä (navigator.userAgent.indexOf('MSIE 6')!=-1). Sen sijaan on huono idea tehdä versionumeroon perustuvia tunnistusyrityksiä, esim. navigator.appVersion.indexOf("5.")>=0. Versionumero voi tarkoittaa selaimen oman versionumeron lisäksi vastaavan Mozillan versionumeroa, Windows-käyttöjärjestelmän versionumeroa (esim. Windows NT 5.0) tai selaimen jakelukanavan versionumeroa (esim. AOL 5.0). Mahdollinen tunnistusjono voi olla esim. Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.0).

    2. Jotkut MS IE -selaimen versiot käyttävät poikkeuksellisia versionumeroiden tunnistusjonoja, esim. MSIE+5.5+. Jos versionumeroa kysytään poikkeukselliset versionumerot saattavat jäädä huomioimatta.

    3. Yksilöinnistä puuttuu MS IE Windows ja Mac -selaimien erittely. Ne voi toteuttaa (navigator.userAgent.indexOf('Mac')!=-1) ja (navigator.userAgent.indexOf('Win')!=-1) ehdot lisäämällä. älä käytä käyttöjärjestelmien täydellisiä nimiä, sillä jotkut selaimet käyttävät esim. tunnistusjonoja Win32 ja Mac_PPC.

    4. Operalla on monta esittäytymismoodia ja ne useimmiten osittain "valehtelevat". Opera on yleensä esittäytymismuodossa Esittäydy: MSIE 5.0 (engl. Identify as MSIE 5.0). Opera saattaa saada huonon CSS:n tai se ei saa CSS:ää ollenkaan ratkaisuissa, jossa kysytään vain selainten nimiä ja versionumeroita riippuen tietenkin siitä, millä tavalla selaimet on tunnistettu. Tavat, joilla olen tunnistuttanut Netscape 4.x ja Netscape 6.x+ -selaimet ovat sellaisia, että ne eivät koske Operaa, vaikka selain teeskentelisi olevansa jokin Netscape-selain. Mikäli tunnistukset ovat sisäkkäisiä ne saattavat hidastaa skriptien käsittelyä.

    5. Operan todellista versionumeroa ei ole mahdollista tunnistaa navigator.appVersion.indexOf('5.')>=0 avulla koska Opera vain palauttaa sen selaimen versionumeron, joka se teeskentelee olevansa.

    6. Vaikka Opera olisi missä tahansa esittäytymismoodissa, ainakin sangen uudet versiot voi kuitenkin aina tunnistuttaa omalla nimellään, mutta tämä tunnistus tulee laittaa ennen muita selainkohtaisia tunnistuksia.

    7. Opera 4.x on herkkä sille, että kenoviivan (\) välilyönti merkitään kenoviivalla ja sen jälkeen on vain yksi välilyönti eikä ylimääräisiä rivikatkoja ole. Pienen virheen vuoksi Opera 4.x ei toteuttanut ensimmäisissä testeissäni JavaScript koodausta. Jos rivikatkot tekevät koodin selvemmäksi, koodi täytyy katenoida esim. seuraavasti:

      document.writeln('\<lin'+
         'k\ rel=\"stylesheet\"\ type=\"text\/css\"\'+
         'href=\"..\/Css\/'+sStyleFile+'\"\ media=\"'+
         sStyleMedia+'\"\ \/\>');

    8. Erään saamani s-postin mukaan Opera 3.x -selaimille ei voida varmuudella antaa CSS:ää, joka olisi tarkoitettu selaimille, jotka eivät tue selainkohtaista DHTML:ää tai DOM1:tä sillä selain ei aina ilmoittaisi selaimen omaa versionumeroa. En tiedä onko väite tosi. Ainakin Opera 3.62 EPOC ilmoittaa aina selaimen oman versionumeron.

    9. Kännyköiden kohdalla Symbian OS -selaimet käyttävät esittäytymisjonoissaan käyttöjärjestelmästä jonoa EPOC. Sikäli kuin tiedän vain Opera 5.x+ ovat selaimia, jotka tukevat dynaamisia valikoita.


      Opera for Symbian: General Opera information.
    10. Opera 4.x-5.x -selaimet kärsivät hieman toisessa, kolmannessa ja neljännessä vaihtoehdossa. Ne eivät lue JavaScript koodausta kun käytetään selaimen eteen- ja taaksepäin nuolia (tai muita vastaavia toimintoja). Mikäli vierailija ei valitse joka kerta uutta sivua em. selaimet näyttävät toisessa ja kolmannessa ratkaisussa linkit siten kun muut modernit selaimet näyttävät ne tilanteissa, joissa JavaScript on kytketty pois toiminnasta. Haitta koskee kuitenkin harvoja vierailijoita.

    11. Jos Mozilla Gecko -selaimet halutaan eritellä tarkemmin, suosittelen Build ID eli luontipäivään perustuvia lisätunnistuksia. Ne voidaan liittää esimerkeissäni käyttämiin tunnistuksiin. Esim. (Gecko && (parseInt(navigator.productSub)>=20011018)) koskee Netscape 6.1/ Mozilla 0.9.1 ja sitä uudempia selaimia. Jos haluat voit erottaa Netscape -selaimet Mozilla -selaimista esim. lisäehdolla navigator.vendor == ("Netscape7") ja antaa siten Netscape -selaimille eri päivämäärän kuin Mozilla -selaimille. Periaatteessa erottelun voisi toteuttaa myös tarkennetulla versionumerolla, esim. userAgent.indexOf('Netscape6\/6.1'). Netscapea käsittelevällä sivulla[S] on päivämäärälista ja tunnistusesimerkkejä.

    12. Voit käyttää mallina käyttämääni kommentoitua lähdekoodikatkelmaa[S]. Myös s-postiystäväni sivuilta löytyy lisää tunnistusmalleja.


    13. Linux käyttöjärjestelmässä voidaan käyttää Konqueror-selainta. Selain kirjoittaa oletusarvoisesti selaimen nimen ja versionumeron ja se käyttää omaa esityskonetta. Tällöin se voidaan tunnistuttaa omalla nimellään, mutta mukaan on syytä laittaa lisäehto (käyttämieni esimerkkien pohjalta se olisi && !Gecko), sillä Konqueror-selaimen voi määritellä käyttämään Mozilla Gecko esityskonetta. Selaimen käyttäjä voi kuitenkin muuttaa esittäytymismerkkijonoa, joten selainta ei voi täysin luotettavasti tunnistaa.

    14. Kun suunnitellaan tunnistukset tulevaisuuden selaimien kanssa yhteensopiviksi, voi olla mielekästä eliminoida kirjainten "kastin" vaikutus selainten esittäytymisjonoissa. Laittamalla toLowerCase(). or toUpperCase(). ennen indexOf mahdollinen kirjainkoon vaihtelu ei haittaa (esim. toLowerCase().indexOf('win') toimii sekä jonojen Windows että WINDOWS kanssa).

    15. Käsittelen eräällä toisella sivukokonaisuudella PHP:hen perustuvia selaintunnistuksia[S]

  3. Kaikki linkit ovat itse sivulla, mutta kerrokset määrittelevät elementit tuotetaan skriptien avulla, jolloin kaikki linkit ovat näkyvissä, jos JavaScript on pois päältä. Alla on esimerkki aloitusmerkkauksista (niille pitää kirjoituttaa pariksi päätösmerkkaukset):

    <script language="JavaScript" type="text/javascript">
    <!--
    if (document.layers)
    {document.writeln('\<lay'+'er\ id=\"Kerros1\"\ class="\pageGroup\"\...\>');}

    else {document.writeln('\<di'+'v\ id=\"Kerros1\"\ class="\pageGroup\"\...\>');}

    //-->
    </script>
  4. On myös mahdollista luoda kahden edellisen vaihtoehdon yhdistelmä. Tässä ratkaisussa suurin osa CSS:stä voisi olla päätiedostossa mukaan lukien suurin on kerroksiin liittyvästä CSS:stä. Vain pieni osa olisi erityisesti dynaamisille valikoille tarkoitetussa tiedostossa. Vaikka selain ei lukisi dynaamisille valikoille tarkoitettua CSS-tiedostoa, dynaamiset valikot voisivat toimia ainakin jollakin lailla, jos selain vain luo tarpeelliset elementit.

  5. Valikossa on selkeällä paikalla linkki erityiselle linkkisivulle, josta löytyy jatkolinkit kaikille välttämättömille sivuille. Valikon ei tarvitse olla välttämättä oletusarvoisesti esillä. Valikon paikalla voi olla yksi linkki, joka vie erityiselle linkkisivulle, joka voi olla esim. suuri linkkitaulukko.

  6. Tilanteissa, joissa JavaScript on pois päällä, tulee näkyviin vaihtoehtoinen linkistö. Perus CSS-tiedosto päättyy kohtaan, joka määrittelee dynaamiset linkit piilotettaviksi ja vaihtoehtoiset linkit esitettäviksi. Alla on esimerkki tällaisesta ratkaisusta:

    /* Seuraava CSS on basicScreen.css tiedoston lopussa: */
    #alternativeLinkSet {display:block;} /* Vaihtoehtoisen navigoinnin linkit. */
    #tableAllPages {display:none} /* Dynaamisten valikoiden linkit. */


    /* Seuraava CSS on layers.css-tiedoston alussa: */
    #tableAllPages {display:block}
    #alternativeLinkSet {display:none}

    Selainkohtaisia huomautuksia:

    1. Jos CSS komentaa vaihtamaan ominaisuuksien arvoja paljon CSS:ää on useissa eri tiedostoissa, tilanne kuitenkin "stressaa" selaimia. Huomasin eräässä kokeilussa, jossa selaimen oli tarkoitus saada vaihtoehtoiset linkit tilanteessa, jossa JavaScript-tuki olisi pois päältä, että MS IE 5.0 Windowsilla sivu täytyi ladata uudestaan. Tämä saattoi liittyä CSS:ään (ja/tai servereihin), mutta ei välttämättä, sillä CSS oli osittain JavaScript-riippuvainen. Yksi keino - tosin ei välttämättä toimiva - tämän ongelman välttämiseksi olisi saattanut olla kirjoituttaa CSS skripteillä seuraavan esimerkin tapaisesti myös se, että vaihtoehtoinen linkistö piilotetaan ja dynaaminen linkistö näytetään:

      <script language="JavaScript" type="text/javascript">
      <!--
      {document.writeln('\<sty'+'le\ type=\"text\/css\"\>');
      document.writeln('\<'+'!--');
      document.writeln('#alternativeLinkSet\{display:none\}');
      document.writeln('#tableAllPages\{display:block\}');
      document.writeln('--'+'\>');
      document.writeln('\<\/sty'+'le\>');}

      //-->
      </script>
    2. Edellinen ratkaisu ei poista toista ongelmaa, joka liittyy vaihtoehtoisiin linkkeihin. Vaihtoehtoisen linkistön toinen heikkous on siinä, että JavaScript- tuen poissa ollessa Netscape 4.x näyttää sekä vaihtoehtoiset linkit että dynaamisten valikoiden linkit, sillä JavaScript-tuen pois ottaminen kytkee pois päältä myös CSS-tuen. Myös selaimet, jotka eivät tue lainkaan CSS:ää saavat kaksi linkistöä.

Erilaisissa tavoissa antaa erilainen CSS tilanteille, joissa JavaScript tuki on päällä/ pois päältä on joitakin ongelmia, jotka voivat johtua servereistä, JavaScript-koodin käsittelystä tai CSS:n käsittelystä. Jos palvelin joutuu kasaamaan CSS:n monesta palasta, selain ei välttämättä saa sitä riittävän nopeasti, jolloin se saattaa esittää sivun virheellisesti. Jos yhteydet ovat hyvät, CSS:n ei pitäisi aiheuttaa ongelmia.

[Alku]

Käytetty JavaScript-koodaus

Aiheet

Mallitiedostot

DHTML/DOM valikoissa JavaScrip-koodaus liittyy HTML ja CSS-koodaukseen. Systeemi tarvitsee toimiakseen yhden JavaScript- ja muutaman CSS-tiedoston sekä ohjauksen dokumentin HEAD-elementin sisään sekä BODY-elementin sisälle ns. tapahtumankäsittelijöihin (event handlers). Seuraavia mallitiedostoja (olen käyttänyt niitä suomen- ja englanninkielisillä CSS-sivuilla) voi käyttää apuna suunniteltaessa dynaamisia valikoita:

Yleisiä huomautuksia:

[Alku]

Funktiot

Dynaamisten valikoiden linkit voivat olla itse sivulla tai ne voidaan tuotattaa JavaScript-koodauksilla or palvelinpuolen systeemeillä. Esimerkkisivuilla linkit ovat taulukoissa. JavaScript, jota olen käyttänyt määrittää vain sen, mitkä valikot paljastetaan/ piilotetaan ja millä tavalla paljastaminen/ piilottaminen tapahtuu.

Dynaamisten valikoiden toimintaidea on hyvin yksinkertainen. Sivun tekijä määritellään lohkoja, jotka toimivat dynaamisina valikkoina. Näille annetaan id-attribuutti, joilla on tapahtumankäsittelijöissä vastaava arvot eli parametrit (käytetään myös nimitystä argumentit). Yleisimmät tapahtumankäsittelijät ovat onmouseover, onmouseout ja onclick - viimeksi mainittu voidaan korvata href="javascript:" tilanteissa, missä ei tarvita tapahtumankäsittelyn ohella tavanomaista linkitystä). Opetan niiden käyttöä. Funktioita, jotka Web-suunnittelijan täytyy tunnistaa dynaamisten valikoiden suunnittelussa on vain kolme:

[Alku]

Ajastetut valikot

Sivujen tekijä sitten vain päättää, mitkä valikot toimivat milläkin tavoin. Alla on hieman editoitu kuvakaappaus englanninkielisestä esimerkkisivusta[S]:


CSS-site

Valikossa on ajastinfunktioita ja se käyttää seuraavaa systeemiä (mukana on lyhenneltyjä koodiesimerkkejä):

  1. Päävalikosta siirrytään toiselle tasolle joko liikuttamalla hiirtä oikealle (mikäli linkkiä tulisi vahingossa klikattua, siirrytään toiselta tasolta valitun sivuryhmän ensimmäiselle sivulle) tai klikkaamalla nuolissa () olevia linkkejä. Jonkun alivalikon valitseminen sulkee avoimet toisen tason valikot:

    <a href="index2.php3#Full" onmouseover="ajastin_pois(); MM_showHideLayers('indexPages','','hide','allSites','','hide','Generic','','show',...);" title="">Generic</a>
    tai
    <a href="javascript:ajastin_pois(); MM_showHideLayers('indexPages','','hide','allSites','','hide',...);" title="..."> <img src="..." title="..." alt="..."/></a>
  2. Toisella tasolla valikosta poistuminen sulkee valikon hetken päästä ajastettuna. Toiselta tasolta siirrytään kolmannelle tasolle samalla periaatteella kuin ensimmäiseltä tasolta toiselle. Alla toisen valikon esillä pitävät ja sen sulkevat komennot:

    <div id="Generic" class="pageGroup" onmouseover="ajastin_pois(); MM_showHideLayers('Generic','','show');" onmouseout="piilota_valikot_hitaasti('Generic');">
  3. Kolmannen tason valikko pitää toisen tason valikon avoimena. Kolmannen tason valikko voi sulkeua nopeasti kun valikosta itsestään poistutaan:

    <div id="Generic1" class="pageGroup" onmouseover="ajastin_pois(); MM_showHideLayers('Generic','','show','Generic1','','show');" onmouseout="MM_showHideLayers('Generic','','show'); piilota_valikot_nopeimmin('Generic1');">

Edellä esitetyllä ratkaisulla on sangen paljon yleisiä ja selainkohtaisia JavaScript-koodaukseen liittyviä ongelmia

Yleisiä huomautuksia:

  1. Säilytinelementille annetuilla komennoilla on suurempi painoarvo kuin linkeille annetuilla komennoilla - säilytinelementin sisällä olevat linkit eivät voi muuttaa säilytinelementin määrittämiä show/ hide komentoja, jos komennot koskevat samoja elementtejä.

  2. Edellä esitetyn ratkaisun yleinen ongelma on tietyissä tilanteissa kolmannen tason valikon sulkeminen tilanteissa, joissa vierailija siirtää hiirtä vasemmalle, jolloin hän ei käy lainkaan itse kolmannen tason valikossa.


    CSS-site

    Jos vasemmalla ei ole mitään linkkiä, kolmannen tason valikko voi jäädä avoimeksi siihen asti kunnes vierailija siirtyy päävalikkoon. Siksi ajaksi kolmannen tason valikko jää näyttöruudulle "orvoksi". Tämän ongelman voi osittain ratkaista siten, että laittaa kolmannen tason linkin valikon avaavan linkin vasemmalle puolelle läpinäkyvän kuvalinkin tai muutaman kiinteän välilyönnin (&nbsp;), joka (yleensä) sulkee avoinna olevan kolmannen tason valikon. Alla on esimerkki kuvitteellisesta täytekuvasta (ns. spacer-kuva, joka on yleensä läpinäkyvä GIF-kuva):

    <a class="filling" href="#" onmouseover="ajastin_pois(); MM_showHideLayers('AppendixesStandards','','hide');"> <img src="../Kuvat/Css/spacer.gif" width="11" height="15" /></a>

    Tällaiset temput ovat mielestäni ärsyttävän keinotekoisia. Ongelmaksi jää se, että nopeat hiiren liikkeet vasemmalle saattavat jättää kolmannen tason valikoita näkyviin, koska aktiiviset alueet ovat pieniä. Selain ei yksinkertaisesti ehdi reagoimaan tapahtumiin.

  3. Ylimääräinen aktiivinen täytekuva tarvitaan myös tilanteissa, joissa valikon alimmaisin linkki avaa alivalikon. Tässä tapauksessa alapuolella oleva piilolinkki sulkee viimeksi avatun alivalikon.

  4. Jos funktiokutsut muodostuvat kovin pitkiksi ylläpitää, niitä voi koota uusiin funktioihin, esim. (tämä on suomenkielisessä mallisivussa):

    function hideThlMenus() /* Piilota kaikki kolmannen tason valikot. */
    {ajastin_pois(); MM_showHideLayers('GenericPreface','','hide',...);}
  5. Olen havainnut selainten hitauden yleiseksi ongelmaksi. Laitoin siksi päävalikkoon muutamia sellaisia sulkemiskomentoja, joiden käyttö periaatteessa riittäisi toisen tason valikoissa.

Selainkohtaisia huomautuksia:

  1. Erityisesti Opera 5.x-6.x mutta myös MS IE saattaa sulkea ennalta arvaamattomasti alivalikot, jos vierailija selaa linkkejä ylös alas valitsematta mitään sivua. Opera 7.0 Beta1 -selaimessa ei ole stabiliteettiongelmia ajastettujen valikoiden. Valikot toimivat jopa vakaammin kuin MS IE -selaimissa.

  2. Opera 5.x-6.x eivät pidä toisen tason valikkoa täysin luotettavasti auki. Hiirtä tulee liikuttaa, jotta se pysyisi avoimena. Kun hiirtä liikuttaa toisen tason valikko tulee jälleen näkyviin. Koska hiiren liike voi avata sulkeutuneen valikon, käytös on vierailijan mielestä sangen epävakaa, vaikka stabiliteettiongelma on sangen pieni.

  3. Jos kolmannen tason valikossa onmouseout-tilassa ei olisi ajastusta vaan sen sijaan onmouseout="MM_showHideLayers(...,'Generic1','','hide');" ainakaan Netscape 6.1 tasoisella Mozilla 0.9:llä ei pääsisi lainkaan kolmannen tason valikkoon!

  4. Jos esim. kolmannen tason valikko AppendixesStandards suljetaan toisen tason valikon kautta antamalla komento MM_showHideLayers('AppendixesStandards','','hide'); lopputulos on se, että kolmannelle valikkotasolle ei voi päästä lainkaan MS IE 4.x Windows selaimilla, sillä selain toteuttaa säilytinelementille virheellisesti onmouseout-attribuutin (onmouseout vaikuttaa alueilla, joissa ei ole linkkejä, vaikka käytöksen tulisi olla riippuvainen säilytinelementin reunoista)! Jos sulkemisen toteuttaa ajastusfunktiolla piilota_valikot_nopeasti('AppendixesStandards'); Opera 5.x-6.x -selaimissa on taasen vaikeuksia sen kanssa, sillä se aiheuttaa ennalta arvaamatonta valikoiden sulkeutumista! Mielestäni seuraavat komennot toisen tason valikolle eivät ole kovin käyttökelpoisia:

    <div id="Appendixes" class="pageGroup" onmouseover="ajastin_pois(); MM_showHideLayers('Appendixes','','show');" onmouseout="piilota_valikot_hitaimmin('Appendixes'); MM_showHideLayers('AppendixesStandards','','hide');" >
    tai
    <div id="Appendixes" class="pageGroup" onmouseover="ajastin_pois(); MM_showHideLayers('Appendixes','','show');" onmouseout="piilota_valikot_hitaimmin('Appendixes'); piilota_valikot_nopeasti('AppendixesStandards');" >
  5. Selaimet toimivat paremmin, mikäli ajastus ei ole itse linkeillä (elementti A) vaan lohkolla, jonka sisällä valikoiden linkit ovat eli ns. esi-isäelementillä (anchestor element), säilytinelementillä (container element; säilytinlohkon täytealueet (padding) kuuluvat sen aktiiviseen alueeseen, mutta mahdolliset reunukset ja marginaalit eivät). Ajatuksen antaminen yksittäisille linkeille aiheuttaa välkyntää, linkit häviävät käytettävistä milloin missäkin tilanteessa eikä niitä saa välittömästi uudelleen auki - käytettävyys on ylipäätänsä huono! Erityisesti Opera 5.x-6.x:lla on ongelmia. Samat ongelmat ovat hieman lievempänä MS IE Windows -selaimissa. Valikoiden sulkeminen emoelementin avulla ei kuitenkaan toimi Opera 5.x-6.x:ssa aina odotetulla tavalla, mikäli ajastinfunktioita käytetään (selain saattaa sulkea valikon ennalta arvaamattomasti).

  6. Netscape 4.x -selaimissa linkkien säilytinelementteinä toimivat edellä mainitulla tavalla vain LAYER ja ILAYER elementit. Tämä on toinen niistä syistä, miksi käytän LAYER elementtejä. Jouduin käyttämään niitä Netscape 4.x -selaimilla myös siksi, että CSS ei toiminut kaikissa yhteyksissä JavaScript-koodauksen ja DIV elementtien kanssa kuten se toimii kaikkien muiden DHTML/DOM tukevien selainten kanssa. JavaScript toimii kuitenkin LAYER elementtien kanssa. Tosin minulla oli vaikeuksia saada JavaScript-koodaus toimimaan ensimmäisen haluamani LAYER elementin kanssa. Poistin JavaScript-koodauksen kanssa asemointiin liittyvän CSS:n vastaavalta DIV elementiltä (muut selaimet saavat sen linkitettynä). Lisäsin eräässä kehittelyvaiheessa muodollisia "valikoita" (<div id="foo" style="visibility:hidden"></div>), joita en enää tarvitse. Jouduin satunnaisissa tilanteissa tuotattamaan ylimääräisen LAYER elementin, jotta ensimmäinen valikkoihin liittyvä elementti toimisi oikein. Sain lopulta kaikki haluamani valikot toimivat LAYER elementtien kanssa. Olen tuotattanut LAYER elementtejä seuraavan kaltaisten skriptien avulla:

    <script language="JavaScript" type="text/javascript">
    <!--
    if (document.layers)
    {document.writeln('\<lay'+'er\ width=\"120\"\ visibility=\"hidden"\ top=\"66\"\ left=\"141\"\ id=\"MainPages\"\ bgcolor=\"white\"\ onmouseover=\"ajastin_pois(); MM_showHideLayers(\'MainPages\',\'\',\'show\');\"\ onmouseout=\"piilota_valikot_hitaasti(\'MainPages\');\"\>');}

    //-->
    </script>
  7. Saamani s-postin mukaan onmouseover tapahtumankäsittelijäattribuutit eivät aina toimi MS IE 5.0 Mac -selaimissa. Tästä syystä joissakin kehittelyversioissa joillakin sivuilla vain javascript:... komennot avasivat alivalikot. Jos mahdollista dynaamisten valikoiden toimivuus tulisi testata myös MS IE 5.0 Mac -selaimissa. MS IE 5.0 Mac -selainten kaltaisia ongelmia on kokemukseni mukaan Opera 4.x:ää, mutta niitä ei ole tarpeen ottaa huomioon.


[Alku]

Ei-ajastetut valikot

On kaiketinkin tullut ilmeiseksi, että edellä olleen esimerkin ajastinfunktiota käyttävässä "ratkaisussa" on mielestäni aivan liian paljon selaimen vakauteen ja sekä valikoiden sulkemiseen liittyviä ongelmia. Niistä voidaan päästä toisenlaisella suunnittelulla. Seuraavat ratkaisut toimivat paremmin:

  1. Valikoilla on erityinen sulkemislinkki.

  2. Valikot suljetaan tarvittaville sivustoille piilotettujen linkkien avulla.

  3. Valikoiden sulkeminen tapahtuu silloin kun sivulla vierailija siirtyy asiasisältöön (dynaamiset valikot eivät saa olla tässä ratkaisussa varsinaisen sisällön keskellä). Sulkemisfunktioille ei tule laittaa ole ajastinta, sillä Opera 5.x-6.x toimivat hyvin vain jos ajastinta ei käytetä. Selaimilla saattaa ilmetä pientä viivettä ennen kuin ne sulkevat avoinna olevat valikot. Kyseessä on kuitenkin sangen harmiton viive, sillä selaimet aina sulkevat valikot kun vierailija liikuttaa hiirtä.

Edellisen listan kaksi ensimmäistä kohtaa ovat kuitenkin tarpeettomia. Useimmille selaimille luotettavimmin toimiva ratkaisu seuraavanlainen:

Taustalaatikko

Varjolaatikko

Jos tarkoituksena on että valikot sulkeutuvat automaattisesti onmouseover-attribuutin avulla nämä ovat ainoat mahdolliset tavat, joilla dynaamiset valikot toimivat mahdollisimman luotettavasti MS IE 5.x+ (Mac ja Windows), Opera 5.x+ ja Mozilla Gecko -selaimissa. Erityisesti ratkaisuni parantaa dynaamisten valikoiden toimivuutta Opera 5.x-6.x -selaimissa monitasoisia alivalikoita käytettäessä. Painotan kuitenkin, että kaikkien em. selainten kohdalla on todettava, että valikot toimivat niissäkin mahdollisimman virheettömästi. Myös MS IE:n käyttäjät voivat olla täysin tyytyväisiä ratkaisuuni. Mielestäni (vähintään) kolmitasoinen valikkosysteemi toimii hyvin vain, jos se täyttää seuraavat vaatimukset (valikkosysteemini täyttää kaikki nämä vaatimukset ainakin jollakin variaatiolla):

  1. Alivalikot toimivat absoluuttisen vakaasti kaikissa tilanteissa. Esim. kun kolmannen tason valikko on auki, sen "emovalikkona" (valikko, joka avaa seuraavan tason valikon) toimiva toisen tason valikko pysyy luotettavasti avoinna.

  2. Alivalikot eivät koskaan sulkeudu ennalta arvaamattomasti (lasken kaikki tilanteet, joissa valikko sulkeutuu, kun valikoissa vierailija on valikkolohkon sisällä ovat ennalta arvaamattomiksi tilanteiksi esim. tilanteen jossa vierailija selaa linkkejä ja valikko häviää alta).

  3. Alivalikot eivät koskaan sulkeudu ennen kuin vierailija on ohittanut koko valikkolohkon.

  4. Vierailtu alivalikko sulkeutuu kun vierailija siirtyy pois koko valikkolohkosta lukuun ottamatta tilanteita, joissa hiiri on paikassa, joka avaa seuraavan tason alivalikon.

  5. Emovalikko on näkyvissä koko sen ajan, kun vierailija on viimeksi avatulla valikkotasolla.

  6. Valikossa ei synny tilannetta, että alivalikko jää "orvoksi" (esim. kolmannen tason alivalikkon on orpo, jos se on näkyvissä tilanteessa, jossa sen emovalikko on piilossa).

  7. Kun vierailija on mennyt minkä tahansa alivalikon viimeiselle alivalikkotasolle hän voi alivalikosta samaa "polkua" pitkin ensimmäisellä tasolla olevaan päävalikkoon.

Ratkaisuni erityisedut ovat seuraavat (monia niistä ei ole mahdollista välttää muilla ratkaisuilla):

  1. Tässä ratkaisussa ei tule koskaan vakavia ajastinviiveiden aiheuttamia ongelmia.

  2. Mitään ylimääräisiä keinotekoisia täytekuvia ei tarvita.

  3. Erilliset sulkemislinkit ovat tarpeettomia.

  4. Tapahtumankäsittelijäattribuuttien määrä voidaan minimoida ja onmouseout ei tarvita välttämättä lainkaan alivalikoiden sulkemiskomennoissa.

  5. Valikot voivat olla hyvin monitasoisia ilman merkittäviä ongelmia. Olen käyttänyt neljätasoisia valikoita ja ovat toimineet yhtä virheettömästi kuin toisen tason valikotkin.

  6. Tämä on äärimmäisen helppo ratkaisu Web-suunnittelijoille (heidän tulee kuitenkin tietää, missä selaimissa se toimii).

  7. Jos valikon tekijä jättää linkkien ympärille tarpeeksi tyhjää tilaa (ja/tai valikoilla on taustalaatikot) valikon käyttäjä ei vahingossa sulje niitä. Tällöin nopeasti sulkeutuvat valikot tuntuvat sangen miellyttäviltä.

Ratkaisun rajoitteet ja haitat ovat seuraavat:

  1. Ratkaisun ainoa merkittävä rajoite on se, että "mukavan pehmeitä" viiveitä ei ole käytetty. Windows XP:n käyttäjät ovat niihin tottuneet (en henkilökohtaisesti tykkää hitaasti ja pehmeästi avautuvista pudotusvalikoista. Selainten täytyy kuitenkin toimia internetissä paljon epävakaammissa olosuhteissa kuin tavanomaisten sovellutusten vakaassa käyttöjärjestelmässä. Ei ole järkevää pyytää Web-sivun toimivan kuin MS Word. Toki viiveajat haittaavat toisia selaimia vähemmän kuin toisia. Jos - kuten moni suunnittelija tekee - ei välitetä enemmän tai vähemmän heikentyneestä toimivuudesta jossakin selaimessa viiveitäkin voi käyttää.

  2. Valikoita ei voi laatia siten, että viimeisimmän avatun alivalikkotason kokonaan ohitettua vain viimeinen alivalikkotaso häviää näkyvistä mutta edelliset alivalikkotasot jäävät näkyviin. Tällaista käytöstä vierailijat eivä kuitenkaan yleensä kaipaa, sillä jos edelliset tasot jäisivät aina näkyviin, ne täytyisi varta vasten käydä sulkemassa. Se loisi vierailijalle lisätyötä, mitä pidetään yleensä epämiellyttävänä piirteenä. Systeemissäni on aina mahdollista palata samaa polkua myöten päävalikkoon, mutta polulta "liukastuminen" sulkee kaikki avoimet alivalikot. Liukastuminen voidaan tosin haluttaessa eliminoida taustalaatikoilla.

  3. Ratkaisuni pienenä haittana on se, että MS IE 4.x Windows -selaimelle paras mahdollinen ratkaisu edellyttää lukuisten varjolaatikoiden käyttöä. Varjolaatikoista on tiettyjä etuja myös muille selaimille. En kuitenkaan pidä järkevänä luoda niitä pelkästään MS IE 4.x Windows takia. MS IE 4.x Windows on harvinaiseksi käyvä selain ja tämän haitan merkitys vähenee päivä päivältä.

Selainkohtaisia huomautuksia:

  1. Jos dynaamisten valikoiden rakenne on erityisen raskas olen havainnut, että siirryttäessä kolmannen tason valikoista toisen tason valikoihin MS IE 6.0 Windows (koskee todennäköisesti myös 5.x sarjaa) saattaa sulkea valikot ennalta arvaamattomasti, jos sisällysluettelo sulkee kaikki valikot onmouseover tai onmousemove attribuuttien avulla. Huomasin, etten ollut määritellyt z-index ominaisuutta dynaamisten valikoiden pohjaelementille ja sivun pääsisällölle. MS IE tuli epätietoiseksi mitä komentoa sen tuli seurata. Asetin ne ja toimivuus parani hieman, mutta ongelma ei kokonaan poistunut.

    Sain ratkaistua ongelman vain määrittelemällä koko valikolle aktiivisen taustalaatikon. Taustalaatikolle on järkevää asettaa joko onmouseover or onmousedown attribuutti koska onmouseout käytettäessä valikot sulkeutuvat kun vierailija ensin poistuu koko valikosta ja palaa takaisin johonkin taustalaatikon sisällä olevaan valikkoon. Värillisen taustalaatikon kanssa ei tullut ongelmia. Läpinäkyvä taustalaatikko toimi huonommin. Testeissäni onmousedown väriselle taustalaatikolle ja onmouseover sisällölle annettuna toimivat. Jos taustalaatikolle käytetään onmouseover attribuuttia sisällölle pitää asettaa joko onmousedown tai onclick attribuutit. Ongelmallisissa tilanteissa on järkevää ettei valikoita suljeta lainkaan asiasisällön kautta tai että asiasisällön kautta tapahtuvat sulkemiskomennot on suunniteltu niin, etteivät ne koske MS IE 6.0 -selaimia. Mikäli alivalikoille laitetaan varjolaatikot, sisällön kautta sulkemisessakaan ei tule ongelmia.

  2. MS IE 4.x Windowsissa valikon sulkeminen onmouseover or onmousemove attribuuttien avulla suoraan alla olevan sisällön kautta aiheuttaa sen, että alivalikot eivät pysy aina auki ja valikot ovat äärimmäisen epävakaita. Kokeilin onmousedown avulla valikon sulkemista mutta linkkejä on vaikea avata eikä sekään toimi toivotulla tavalla. Vain onclick attribuuttia voi käyttää valikon sulkemiseen alla olevan elementin avulla. Jos em. selainta halutaan tukea, sisällön kautta sulkeminen pitäisi toteuttaa ehdollisesti JavaScript-koodauksella document.write() metodia käyttäen niin, että tietyt attribuutit eivät koske MS IE 4.x Windows -selainta. Valikot saattavat jääjä auki, mutta se on parempi tilanne kuin se, että alivalikoiden linkkejä ei voi lainkaan käyttää.

    Alla olevassa esimerkissä funktion hideAllGroups() tehtävänä on sulkea kaikki avoimet alivalikot asiasisällön avulla. Seuraavan koodin lisääminen ennen dokumentin asiasisältöä alkua pakottaa kaikki dynaamisia valikoita tukevat selaimet sulkemaan ainakin jollakin tapahtumankäsittelijällä kaikki avoimet alivalikot (kaikki alla olevia tapahtumankäsittelijöitä ei tarvitse laittaa):

    
    <script language="JavaScript" type="text/javascript">
    <!--
    if (document.getElementById)
    {document.write('\<di'+'v\
     onmousedown=\"hideAllGroups();\"\
     onmousemove=\"hideAllGroups();\"\
     onmouseover=\"hideAllGroups(); \"\>');}
    
    else if (document.layers)
    {document.write('\<layer\ z-index=\"0\"\ 
     onmouseover=\"hideAllGroups();\"\>');}
    
    else if (document.all)
    {document.write('\<di'+'v\
     onclick=\"hideAllGroups();\"\>');}
    
    else {}
    //-->
    </script>
    Asiasisältö alkaa tästä...

    Jos valikon taakse laittaa taustaelementin ja/tai jokaiselle alivalikolle omat varjolaatikot, joilla ei ole em. selainta koskevaa tapahtumankäsittelijäattribuutteja, valikon voi sulkea asiasisällön kautta millä tahansa tuetulla tapahtumankäsittelijäattribuutilla, koska asiasisältö ei ole suoraan valikon alla. Taustaelementti ja/tai varjolaatikot toimimat tällöin "eristeenä" valikon ja asiasisällön välillä.

  3. Jos varjot on asemoitu absoluuttisesti määritellyn elementin pohjalta, Opera 5.x ei välttämättä asemoi niitä oikein. Käytä selainkohtaista CSS:ää Opera 5.x:lle tai älä käytä sisäkkäisiä asemointeja.

  4. Kuten aiemminkin on tullut esille kaikki rakenneratkaisut eivät toimi MS IE 5.0 Mac -selaimissa, minkä vuoksi yksinkertaisiin rakenteisiin pyrkiminen on eduksi (jos voit käydä lävitse englanninkielinen testisarja[S] MS IE 5.0 Mac -selaimilla).

  5. Valikoiden sulkeminen sisällön kautta edellyttää Netscape 4.x -selaimissa sitä, että varsinainen sisältö on LAYER or ILAYER elementin keskellä.

  6. Alivalikoiden sulkeminen sisällöstä käsin edellyttää sitä, että koko varsinainen sisältö on LAYER tai ILAYER elementtien sisällä.

Mikäli haluat enemmän ohjeita suosittelen vierailemaan muilla sivustoilla. Löydät hyviä vihjeitä TechsOfTheWeb-sivustolta.

TecsOfTheWeb.Com: Using and Manipulating Dropdown Windows.

[Alku]

Asemointi

Aiheet

Visibility & position

Kaikissa muissa DOM/DHTML tukevissa selaimissa paitsi Netscape 4.x -selaimissa asemointi perustuu yksinomaan CSS:ään. Kunnolla tuettuja ominaisuuksia ja niiden arvoja ovat position:absolute, top ja left. Näiden lisäksi sivujen suunnittelijoiden tulee määritellä pinotaso käyttäen ominaisuutta z-index, jos suurempi arvo merkitsee korkeampaa asemaa elementtien muodostamassa pinossa. Oletus näkyvyysarvo on yleisimmin päävalikolla visibility:visible ja alivalikoilla visibility:hidden. Näitä arvoja sitten muutetaan JavaScript-koodauksella.

Jos valikoita suljetaan sisällön kautta, sekä valikon pohjaelementille että asiasisällölle tulee antaa z-index ominaisuus, jotta valikot olisivat oikeassa pinotasosuhteessa myös varsinaisen asiasisällön kanssa. Mikäli pohjatason elementille ei ole määritellä pinotasoja, mikä tahansa jäljessä tulevan asiasisällön elementti, jolle on määritelty pinotaso tulee asettaa valikon yläpuolelle. Valikkoelementin sisällä olevat pinotasot ovat tällöin suhteessa vain keskenään eivätkä suhteessa Web-sivun asiasisältöön.

Tällä tavoin määritellyt elementit eivät vaikuta millään lailla toisten elementtien asemointiin. Esim. position:absolute; top:50px; left:50px; width:600px; height:400px; visibility:hidden vaikutus on käytännössä sama kuin sillä, että elementillä olisi display:none. Asemoituna ja piilotettuna linkit eivät lainkaan tilaa dokumentin muulta sisällöltä!

Esittämääni systeemiä voidaan käyttää kaikissa sellaisissa valikoissa, joissa elementeille voidaan etukäteen määritellä tietty paikka. Tyypillisin ratkaisu on pudotusvalikko, joita olen käsitellyt tällä verkkosivulla. Ratkaisun etu on siinä, että valikoiden aukaiseminen ei koskaan aiheuta koko dokumentin tai siitä suuren osan uudelleen muotoilun tarvetta. Omassa ratkaisussani vain määritellyt valikot paljastetaan niissä paikoissaan, joissa ne todellisuudessa ovat sivulla! Jos valikot tuotetaan "lennosta", ne eivät silloinkaan vaikuta millään tavoin dokumentin muiden elementtien asemointiin - vain valikoiden suorittamisen nopeus ja/tai luotettavuus muuttuu verrattuna linkkeihin, jotka ovat valmiiksi olemassa sivulla!

Koska minulla on samasta perusvalikosta useita eri versioita, kokosin asemointimäärittelyjä ryhmiin sen mukaan, mikä on valikoiden vaaka- tai pystyasemointi (valikoiden nimet ja ominaisuuksien arvot ovat nykyisin eri kuin esimerkissä):

/* toisen tason alivalikoiden vaaka-asemointi ja z-index */
#Generic, #MainPages,... {left:128px; z-index:19;}
/* kolmannen tason alivalikoiden vaaka-asemointi ja z-index */
#MainPagesAppendixes, #Generic1,... {left:266px; z-index:20}
/* kaikkien valikoiden pystyasemointi */
#Pages, #PagesEn,... {top:42px}
#MainPages, #Generic1,... {top:59px}
...

Käyttämissäni esimerkeissä on ollut monitasoisia valikoita. Vaihtoehtona olisi sisentää alemman tason valikkokohdat - alivalikot muistuttaisivat tällöin sisällysluetteloa - vertaa vaihtoehtoja kahden kuvakaappauksen avulla[S].

Selainkohtaisia huomautuksia:

  1. MS IE näyttää elementit, joilla on visibility:visible vaikka ne olisivat sellaisten elementtien sisällä, joille on määritelty visibility:hidden. Selaimen tulee toimia tällä tavoin. Opera piilottaa aina ja uudet Mozilla Gecko (esim. Netscape 6.1) -selaimet position:fixed käytäessä piilottavat virheellisesti tällaiset elementit (engl. testisivu[S]).

  2. Aluksi käyttämissäni dynaamisissa valikoissa viittaamani ominaisuudet eivät useimmiten toimineet testaamassani Netscape 4.x -selaimissa. Annan siksi esimerkkisivuilla vastaavat attribuutit skriteillä tuotetuille LAYER elementeille. LAYER elementillä ei ole position attribuuttia, mutta aiemmassa esimerkissä ollut <LAYER top="66" left="141"> tarkoittaa teoriassa samaa kuin CSS:ssä position:absolute; top:66px; left:141px (ja esim. z-index="3" tarkoittaa samaa kuin z-index:3) - tosin Netscape 4.x asemoi elementtejä vähän eri lailla kuin MS IE ja Opera. Koska LAYER elementit ovat epästandardeja tuotatin ne kaikki skripteillä.

  3. Kun asemoidaan valikoita, on syytä tutustua absoluuttisesti asemoitujen elementtien asemointiin liittyvät yleisohjeeni[S], jotta suuremmilta ongelmilta vältyttäisiin.

Kaikista kehittyneimmillä selaimilla toimii myös position:fixed asemointityyppi. Näin asemoituihin valikoihin pääsee koska tahansa. Olen havainnut, että position:fixed tuo suunnitteluun rajoituksia sillä ainoa järkevä systeemi on se, että päävalikko on pystytasossa ja linkit ovat allekkain. Jos käytettäisiin kaikki ankkurit aiheuttavat ongelmia sillä valikko peittää sisällön alun. Vierailijan täytyisi joka kerta hieman vierittää tekstiä ylöspäin kun sivun sisäisiä linkkejä olisi käytetty - vierailija olisi äkkiä vihainen kuin ampiainen ja kirosanoja piisaisi!

Jos on mahdollista syntyä tilanne, että valikko piilottaa osan sisällöstä, pitäisi olla mahdollista piilottaa koko valikko. Tietenkin tulee olla myös linkki, jolla saa piilotetun valikon uudestaan esille. Alla on muutamia kuvia mahdollista linkeistä, jolla päävalikon saa piilotettua ja paljastettua sekä kuvakaappaus valikosta, joka niitä käyttää.

Kasaa
Kasaa
Laajenna
Laajenna
Luontosivut

Piilottamisen ja paljastamisen voi tehdä myös täysi- tai puoliautomaattisesti. Jälkimmäisessä tapauksessa onmousedown sulkisi sisällön kautta koko valikon. Se paljastaisi myös sivun (vasemmassa, oikeassa tai molemmissa) reunoissa olevat aktiiviset alueet, joilla on onmouseover, jotka tuovat valikon jälleen näkyviin.

Selainkohtaisia huomautuksia:

  1. Kiinteän asemoinnin voi antaa attribuuttivalitsinten avulla, joita MS IE ei ymmärrä, jolloin vain uudet Opera ja Mozilla Gecko -selaimet toimivat sen mukaan:

    div.pageGroup, div#allPages {position:absolute} div[class="pageGroup"], div[id="allPages"] {position:fixed !important}/* Koska attribuuttivalitsimilla on alempi painoarvo kuin id-valitsimilla, kuvauksessa täytyy olla !important-sääntö. */
  2. Systeemi ei toimi aivan ihanteellisesti Opera 5.x-6.x -selaimissa (toimii kunnolla Opera 7.0 Beta 2 lähtien) eikä mitenkään MS IE 5.0 Mac -selaimissa. Se toimii ihanteellisesti ainoastaan uusimmissa Mozilla Gecko -selaimissa (lue puutteista tarkemmin selainten toimivuutta[S] käsittelevältä sivulta, tein myös testisarjan[S] osoittaakseni ongelmia).

  3. Kiinteästi asemoitujen elementtien sijaan voi käyttää JavaScript-koodauksella toteutettuja "kelluvia" elementtejä, jotka pienellä viivellä asettuvat paikoilleen. Toimivuus on kuitenkin jossakin määrin huonompi kuin kiinteästi asemoiduilla elementeillä. Käsittelen tällaisia elementterjä eräällä lisäsivulla[S].

  4. Vaikka Netscape 6.0 ei tue position:fixed asemointityyppiä huomasin yllätyksekseni, että se toimi position:absolute mukaisesti, joten Netscape 6.0 ei tuottanutkaan odottamiani ongelmia.

  5. Olen joskus nähnyt paikallaan pidettyjä valikoita. Koska selaimet nostivat/laskivat elementtejä toimivuus oli melko huono. En osaa opettaa sellaisten skriptien laatimista, jotka aikaansaisivat (ainakin osittain) paikallaan pysyvät elementit. Alla on osoite, josta saa valikon Andy Woolleyn tekemä Top Navigational Bar IV (ver. 3.3.19) nimisen valikon, joka on tietyillä asetuksilla useimmissa selaimissa (myös Opera 4.x-6.x) vakaa ja siirtyy rullauksen mukana (oletusasetuksilla valikko on Opera 5.x-6.x selaimissa epävakaa ja Opera 5.x on vaikeuksia ladata valikko).

    Määrittelemällä menu_arrays.js tiedostossa valikoille esim. ,,120,1,,style1,0,"left",effect,1,,1,,,,,,,,,, valikko pysyy näkyvillä ja seuraa hiiren liikettä kunnes toinen alivalikko avataan. Monitasoisissa valikoissa toimivuus on kuitenkin monissa selaimissa melko huono sillä alivalikot seuraavat emovalikkoa ärsyttävällä viiveellä. Toimivuus on paljon huonompi kuin position:fixed Mozilla Gecko -selaimissa. Tämän tyyppiset linkit toimivat parhaiten linkkinuolina, jotka vievät sivun alkuun (mallisivu[S]) ja edelliselle/seuraavalle sivulle. Tosin Andy Woolleyn Milonic sivustolla monitasoinenkin valikko toimi sangen hyvin Opera 7.x:ssä (paljon paremmin kuin MS IE 6.0 Windows:ssa) ja kohtalaisen hyvin Opera 6.x:ssäkin (valikko ei kuitenkaan ala toimimaan yhtä nopeasti kuin Opera 7.x:ssä). Valikko on aiemmin mainitsemani valikon uudistettu versio (lataamani versio oli 3.5.08 mutta nykyisin se on todennäköisesti uudempi). Versio 3.5.08 ei lataannu Opera 5.x:ssä aina lainkaan eikä mahdollisesti lataantuessaankaan sovellu Opera 5.x:lle. Tästä ongelmasta voi päästä kirjoittamalla JavaScript, jossa Opera 5.x saa vanhemman valikon (katso tämän sivun lähdekoodi[S]). Yleisesti ottaen tämän tyyppisten valikoiden ongelma on siinä, että ne toimivat vain JavaScript-tuki päällä. Itse valikkorakenne olisi parempi kasata serveripuolen ohjelmoinnilla, joilloin valikko voisi olla ainakin jonkin muotoisena aina käytettävissä. Kokeile PHP:n avulla[S] valikkorakenteen luomista.

  6. Sisällön päälle menemisen ongelmaa voisi periaatteessa helpottaa myös CSS3:een kuuluvalla läpinäkyvyyden (transparency) hallintaan liittyvällä ominaisuudella opacity (= läpinäkymättömyys), mutta yleinen tuki puuttuu em. ominaisuudelta. Netscape 6.2+/ Mozilla 0.9.4+/ vähintään yhtä uusille muille Mozilla Gecko -selaimille voi käyttää -moz-opacity ominaisuutta, joka on väliaikainen opacity ominaisuuden toteutus.

  7. Operan kanssa voisi kokeilla muitakin asemointityyppejä kuin top-left, mutta niiden toimivuus on muissa selaimissa heikko, joten en suosittele bottom-left, top-right ja bottom-right bottom-right asemointityyppien käyttämistä. Yksittäisiä linkkejä tai pieniä linkkikokonaisuuksia voi asemoida niiden mukaisesti, mutta ei dynaamisia valikoita.

[Alku]

Muut vaihtoehdot

Jos valikot määritellään aina samaan paikkaan ja saman kokoisina, valikoiden vaihdot voidaan periaatteessa toteuttaa visibility ominaisuuden arvojen muutosten sijasta z-index ominaisuuden arvojen muutoksilla. En osaa kuitenkaan sanoa, miten laajasti tämä ratkaisu on tuettu.

Sekä visibility että z-index ratkaisujen on siinä, että se ei sovellu valikoihin, joissa elementeille ei voi etukäteen määrittää tiettyä paikkaa. Tämän tyyppinen valikko on esim. Windowsin Resurssienhallinta, josta on alla kuvakaappaus.

Resurssienhallinta

Koska valikkoa voidaan laajentaa missä tilanteessa tahansa, pystytason asemointia ei voi määrittää etukäteen. Elementit pitäisi piilottaa/ paljastaa display:none ja display:block vaihdoilla. Kun elementeille on määritelty display:none niitä ei ikään kuin ole lainkaan koko dokumentissa. Kun niille määritellään display:block ne "raivaavat" itselleen oman tilan.

Ratkaisulla on erittäin ongelmallinen, jos valikoille ei ole varattu lainkaan tai niille on varattu riittämättömästi laajentumistilaa. Valikoiden avaaminen voi aiheuttaa jatkuvaa dokumentin uudelleen muotoilua. Se tuo selaimen toimintaan hitautta ja kaatumisriskin. Kuten olen tuonut esille, ominaisuuden display dynaamiset muutokset eivät ei toimi Opera 4.x-6.x -selaimissa. Vasta . Ymmärtääkseni juuri edellä esittämieni ongelmien vuoksi Opera Software on päättänyt, että sen valmistamat Opera 4.x-6.x -selaimet eivät tue ominaisuuden display dynaamisia muutoksia. Mielestäni display-ominaisuuden dynaamiset muutokset ovat ylipäätänsä huono ratkaisu kehyksettömillä Web-sivuilla, vaikka Opera 7.x+ ja muut modernit selaimet tukevat niitä.

Resurssienhallinnan tapaiset valikot soveltuvat oikeastaan vain kehyksiin, jossa valikko on omassa kehyksessään - sitenhän Windowsin resurssienhallintakin toimii! Vastaavan systeemin saa Java-appleteilla, esim. Auscompin tuotteilla. Java-applettien ongelmana on hitaus ja se, että monet selaimet eivät tue niitä vakiona. Sun Microsystemsin JRE on iso apuohjelma ladattavaksi modeemiyhteyksillä. Dynaamisia valikoita saa myös Flash-animaatioina. Macromedian tuotteiden lisäksi Flash-animaatioita saa muillakin ohjelmilla. Itselläni ei ole mitään kokemusta niiden käytöstä.

Auscomp, Macromedia, Sun Microsystems.

Flash- ja applettivaihtoehtojen edut ja haitat:

Valikoiden luominen on suhteellisen helppo hoitaa kehyksissä myös siten, että JavaScript tai serveripuolen ohjelmointi luo "lennosta" alivalikon avaamisen yhteydessä kokonaan uuden valikkosivun. Tällaiset valikot toimivat myös Operassa.

[Alku]

Ulkoasu

Mitä tulee valikoiden ulkoasuun ongelmat Netscape 4.x -selainten kanssa jatkuvat, koska CSS ei toimi kuin osittain käyttämäni dynaamisten valikoiden kanssa. Varsinkin linkitetyn CSS:n kanssa on vaikeuksia, sillä vain osa siitä toimii. Koska suora CSS toimi paremmin, käytän jonkin verran style-attribuutteja (olen tarvittaessa kumonnut niiden vaikutuksen käyttäen muille selaimille !important-sääntöä). Jouduin lisäämään jonkin verran ylimääräisiä elementtejä (esim. B ja IMG), jotta sain esitysasun riittävän hyväksi. Linkit tuntuivat kaipaavan FONT elementtiä, sillä edes style attribuutti ei aina toimi. Muille kuin Netscape 4.x -selaimille ulkoasu määräytyy pääosin ulkopuolisista CSS-tiedostoista käsin.

Mikäli Netscape 4.x -selaimia tuetaan, dynaamisen valikon HTML-koodi täytyy laittaa aivan sivun alkuun, sillä havaitsin, että Netscape 4.x kaatui, kun se oli keskellä sivua erään taulukon sisällä!

Mielestäni on järkevää asettaa id- or class-attribuutti jokaiselle linkille ja sen emoelementille tai taulukkosolulle, jonka sisällä linkki on (muista, että id-attribuutin arvojen tulisi olla sivukohtaisesti uniikkeja). Tällä tavoin voi sama valikko näkyä joka sivulla hieman erilaisena. Joka sivulla on tyylisivu, joka on sääntö, joka koskee avoinna olevaan sivuun viittaavaa linkkiä. Yksitasoissa dynaamisissa tai staattisissa valikoissa avoinna olevan sivun linkin voi joko piilottaa display:none tai sille määritellään erityiset color ja/tai background-color/ background ominaisuudet. Jälkimmäistä vaihtoehtoa voidaan käyttää myös monitasoisissa dynaamisissa valikoissa. Esim. tällä sivulla on seuraava CSS:

#Dy {background-color:#ffd700 !important; color:#303400 !important}

Se luo seuraavan kuvakaappauksen kaltaisen lopputuloksen:

CSS-site

Ominaisuuksille on asetettu !important eliminoimaan linkki- ja dynaamisten näennäisluokkien (a:visited jne.) vaikutus. Jos linkeillä ei ole alivalikoita, niille voi asettaa myös cursor:default. Merkkaamalla avoinna olevan sivun, sivulla vierailija ei niin helposti klikkaa avoinna olevaa sivua koskevaa linkkiä turhanaikaisesti. Samalla hän voi joka hetki tietää, missä kohtaa hän on valitussa sivuryhmässä.

Uudet Opera, MS IE ja Mozilla Gecko (esim. Netscape 6.x) -selaimet eivät tarvitse kuvalinkkejä, sillä asettamalla tekstilinkille display:block se näyttää ikään kuin kuvalta kuten alla olevassa kuvakaappauksessa (uusilla Opera ja Netscape -selaimilla koko elementti toimii aina linkkinä, mutta MS IE kohdalla toisinaan koko elementti on aktiivinen ja toisinaan ei; jälkimmäisessä tapauksessa display:block saa aikaan vain visuaalisen efektin, mutta vain teksti toimii linkkinä; jos MS IE:llä ominaisuuden width arvo on jokin muu kuin auto, linkit ovat aktiivisia koko käytettävissä olevalta leveydeltään lukuun ottamatta tilanteita, joissa linkit käyttävät ominaisuutta float eivätkä kaikki linkit mahdu samalle riville; ongelmasta voidaan päästä eroon myös lähinnä MS IE 4.x Windowsille esittämälläni tavalla).

CSS-site

Käyttämällä eräitä näennäisluokkia, on mahdollista saada sama lopputulos kuin JavaScript & tapahtumankäsittelijöillä, jotka vaihtavat kuvan or tekstilinkin taustavärin kun hiiri kulkee linkin ylitse/ohitse tai tekee muita toimenpiteitä. Optimaalisen lopputuloksen saavuttamiseksi tarvitaan esim. seuraavat ominaisuudet:

.pageGroup a {display:block; width:100px; height:15px; line-height:15px; margin-top:0; margin-bottom:0; padding-top:0; padding-bottom:0; font-size:12px} /* Ilman line-height ominaisuutta linkkien väliin saattaa jäädä pystytasossa tyhjää tilaa eivätkä tekstilinkit toimi täysin kuvalinkkien tapaan. Jos linkit ovat taulukkosolujen sisällä, myös taulukkosolut tarvitsevat line-height ominaisuuden, jotta saadaan hyvä lopputulos myös Mozilla Gecko -selaimissa (edempänä on tähän asiaan liittyvä koodiesimerkki). Pystytason margin ja padding ominaisuudet on mielekästä asettaa nollaksi, että linkit toimisivat samoin mahdollisimman monessa selaimessa. Fonttikoko kannattaa määrittää siten, että sitä on mahdollisuus isontaa 120%. */
.pageGroup span.link {background:...; padding-left:11px;...} /* Olen joissakin versioissa tekstilinkkien ympärillä elementtiä, joille olen taustaominaisuudet ja padding-left ominaisuuden. Tämä elementtikerros ei ole välttämätön. Suosittelen vain taustavärien asettamista, sillä taustakuva ei toimi kaikissa selaimissa. */
.pageGroup span.Link a:link {background:...; color:...}
.pageGroup span.Link a:visited {background:...; color:...}
.pageGroup span.Link a:hover {background:...; color:...}
.pageGroup span.Link a:active {background:...; color:...}
.pageGroup span.Link a:focus {background:...; color:...}
CSS-siteCSS-site

Koska display:block ei toimi kunnolla Netscape 4.x - ja MS IE 4.x Windows -selaimissa (ks. yllä oikealla puolella oleva kuvakaappaus MS IE Windows -selaimen toteutuksesta ja vertaa sitä vasemmanpuoleiseen kuvaan), ratkaisu ei ole tyylikäs Netscape 4.x - ja MS IE 4.x Windows -selaimissa. Medialohkoja käyttäen luoda CSS, jossa MS IE 4.x Windows ja Netscape 4.x eivät saa tekstilinkeille taustaominaisuuksia (minulla MS IE ongelmia[S] käsittelevällä sivulla joitakin tähän asiaan liittyviä vihjeitä; koska laitoin tekstilinkeille taustaominaisuuksia, ne voivat näyttää em. selaimilla hieman rumilta).

MS IE 4.x Windowsille on tosin mahdollista saada sama lopputulos linkkien emoelementeille annetuilla tapahtumankäsittelijäattribuutilla. Mikäli myös alivalikoiden avaus- ja sulkemistoiminnot toteutetaan emoelementtien välityksellä saadaan illuusio, että linkit ovat koko leveydeltään aktiivisia, esim.:

var nav_over = "this.style.background='#cee8ea';";
var nav_out = "this.style.background='#ffffff';";
...
<div onmouseover="MM_showHideLayers('Generic','','show',...); eval(nav_over);" onmouseout="eval(nav_out);"><a onmouseover="MM_showHideLayers('Generic','','show',...);" href="..."></div>

Vastaavan ratkaisun lisääminen Netscape 4.x:lle kasvattaa koodimäärää rajusti, sillä tarvitaan (jälleen kerran) LAYER-elementtejä.

Tekstipohjaiset linkitkin toimivat kohtalaisen hyvin Netscape 4.x - ja MS IE 4.x Windows -selaimissa, jos linkeillä itsellään ei ole taustaominaisuuksia ja jokainen linkki on omalla taulukkorivillä siten, että sekä linkin vasemmalla että oikealla puolella on taulukkosolu, jossa on kuva ja keskimmäisen solun leveys määritellään kuvalla. Vasemmalla ja oikealla puolella olevissa soluissa olisi linkkejä, jotka avaisivat/ sulkisivat alivalikoita. Vasemmanpuoleisissa soluissa voisi olisi listanappeja. Tarvittaessa myös korkeusarvoja määritellään läpinäkyvillä täytekuvilla.

Edelleen jää jäljelle reunusongelma. Jos reunukset antaa CSS:llä Netscape 4.x jättää taustavärin ja lohkon reunusten väliin muutaman pikselin levyisen läpinäkyvän ruman täytealueen. Lisäksi on huomattava se, että vanhimmat Netscape 4.x -sarjan selaimet kaatuvat CSS-reunuksista. Kokonaisuutta ajatellen tämän eliminoimiseksi on paras keino määritellä taulukolle taustaväri ja luoda "reunukset" joka puolella sisältöä kiertävien taulukkosolujen avulla (soluissa voi käyttää rowspan ja colspan attribuutteja). En ole näin menetellyt kaikkien valikoiden osalta menetellyt vaan ainoastaan päävalikon kohdalla.

Jos taustaväri annetaan elementille LAYER ja sen sisään tulee elementti, jolla on reunukset, ei myöskään synny ongelmaa läpinäkyvistä täytealueesta. Alla on kuvakaappaus testivalikosta. Ratkaisin reunus- ja taustaväriongelmat ensimmäisen tason valikon kohdalla lisäämällä ylimääräisiä taulukkosoluja. Toisen tason valikossa on käytetty tuotettua LAYER elementtiä.

Testisivu

LAYER-ratkaisun etu on helppous ja se se, että myös taustakuvia voi käyttää eikä Netscape 4.x hajota niitä rumasti yksittäisiin taulukkosoluihin. Sillä on myös haittapuolensa. Kuvakaappauksesta näkyy, että taulukkorivien korkeus ei ole sama. Oikeanpuoleisen taulukon ympärillä on lohko, jolla on border ja padding ominaisuudet. Taulukon korkeus vaihtelee tällaisissa tapauksissa, vaikka niissä olisi yhtä monta solua. Ylimääräisten taulukkosolujen lisäetu on siinä, että pystydimensiot toimivat täsmällisemmin. Itse asiassa täsmällisesti toimivat täytealueet vaativat sisällön ympärille reunusten tavoin ylimääräisiä taulukkosoluja (tarvittavien palstojen määrä nousee tällöin seitsemään ja ylimääräisten taulukkorivien neljään).

Tekemässäni mallisivussa[S] on päävalikoissa käytetty seitsenpalstaisia taulukkorivejä mutta alivalikoissa yksinkertaisempia kolmipalstaisia rakenteita. Kaikki valikot sekä yläoikealla valikoihin liittyvät linkkikokonaisuudet ovat skripteillä tuotettujen LAYER-elementtien sisällä. Alla on esimerkki menetelmästä miten luoda ylimääräiset taulukkorivit ja -palstat (koska täytekuvan luonnolliset dimensiot ovat 1x1 pikseliä, ei ole aina välttämätöntä määrittää sekä height että width attribuutteja).

<table summary="" cellspacing="0" cellpadding="0" border="0" bgcolor="white" width="126" >
<tr class="topCells">
<td id="cell1" bgcolor="#303400"><img src="spacer.gif" border="0" alt="" height="1" width="1" /></td>
<td id="cell2" bgcolor="#303400"><img src="spacer.gif" border="0" alt="" height="1" width="2" /></td>
<td id="cell3" bgcolor="#303400"><img src="spacer.gif" border="0" alt="" height="1" width="11" /></td>
<td id="cell4" bgcolor="#303400"><img src="spacer.gif" border="0" alt="" height="1" width="101" /></td>
<td id="cell5" bgcolor="#303400"><img src="spacer.gif" border="0" alt="" height="1" width="8" /></td>
<td id="cell6" bgcolor="#303400"><img src="spacer.gif" border="0" alt="" height="1" width="2" /></td>
<td id="cell7" bgcolor="#303400"><img src="spacer.gif" border="0" alt="" height="1" width="1" /></td>
</tr>

<tr class="paddingCells">
<td rowspan="5" bgcolor="#303400"><img src="spacer.gif" border="0" alt="" width="1" /></td>
<td rowspan="5"><img src="spacer.gif" border="0" alt="" width="2" /></td>
<td colspan="3"><img src="spacer.gif" border="0" alt="" height="5" /></td>
<td rowspan="5"><img src="spacer.gif" border="0" alt="" width="2" /></td>
<td rowspan="5" bgcolor="#303400"><img src="spacer.gif" border="0" alt="" width="1" /></td>
</tr>

<tr class="contentCells">
<td><img src="menuButton.gif" border="0" alt="" height="10" width="10" /></td>
<td>Ekarivi</td>
<td><img src="rightArrowr.gif" border="0" alt="" height="15" width="8" /></td>
</tr>

<tr>
<td><img src="menuButton.gif" border="0" alt="" height="10" width="10" /></td>
<td>Tokarivi</td>
<td><img src="rightArrowr.gif" border="0" alt="" height="15" width="8" /></td>
</tr>

<tr>
<td><img src="menuButton.gif" border="0" alt="" height="10" width="10" /></td>
<td>Kolmasrivi</td>
<td><img src="rightArrowr.gif" border="0" alt="" height="15" width="8" /></td>
</tr>

<tr class="paddingCells">
<td colspan="3"><img src="spacer.gif" border="0" alt="" height="5" /></td>
</tr>

<tr class="bottomCells">
<td bgcolor="#303400" colspan="7">
<img src="spacer.gif" border="0" alt="" height="1" /></td>
</tr>
</table>

Huomasin, että päävalikko toimi pääasiallisena testiselaimena käyttämässäni Operassa hieman hitaammin kuin aiemmin. Ainakin Opera kärsii monimutkaisemmasta rakenteesta, jolla ulkonäkö tuli paremmaksi Netsape 4.x -selaimissa. En suosittele luomaan käyttämääni rakennetta raskaampaa systeemiä. Jos käytetään perusratkaisuna kaksinkertaisia taulukoita laskin, että kohtuullisen hyvän lopputuloksen saamiseksi Netscape 4.x vaatii yli 50% prosenttia enemmän koodia kuin modernit selaimet. Minimikoodaukseen verrattuna Netscape 4.x takia saattaa tarvita lisätä yli kaksinkertainen määrä koodia! On siksi melko kyseenalaista tukea Netscape 4.x -selaimia.

#Pages table, #PagesEn table {width:136px; table-layout:fixed} /* Kun käytetään kiinteää taulukonlaadintaa, yksittäisten solujen kokonaisleveys täytyy täsmätä taulukon kokonaisleveyden kanssa */
#cell1,#cell2, #cell3,... {height:1px; line-height:1px; font-size:1px}
#cell1 img, #cell2 img, #cell3 img,... {height:1px}
#cell1 img, #cell7 img, td#cell1, td#cell7 {width:1px}
...
#cell4 img, td#cell4 {width:105px}
...
.paddingCells td {line-height:5px; font-size:5px; height:5px}
...
div.pageGroup td {height:15px; line-height:15px; padding:0}
/* Solut, joissa on itse linkit. Ilman tätä määritystä rivien korkeus ei ole sama kuin uusissa MS IE ja Opera selaimissa. Ratkaisu ei toimi kunnolla MS IE 4.x Windows -selaimissa, sillä vain osassa soluista rivikorkeus on oikein. */

Vanhanaikaiset HTML 3.2 -tyyppiset rakenneratkaisut aiheuttavat ylimääräistä työtä ja niitä on vaikea saada toimimaan oikein uusissa Mozilla Gecko -pohjaisissa selaimissa. Uusille selaimille olisi paljon järkevämpää poistaa ylimääräiset taulukkorivit (ja jos rowspan attribuutteja on käytetty) samalla myös ylimääräiset taulukkopalstat määrittämällä ylimääräisille taulukkoriveille display:none (päävalikon taulukoihin jäisi tällöin kolme palstaa). Jotta näin voi toimia ylimääräisille taulukkoriveille täytyy määrittää joko id tai class attribuutit (esim. tr.topCells, tr.paddingCells, tr.bottomCells {display:none}). Tällöin voitaisiin määrittää todelliset padding ja border ominaisuudet päävalikon säilytinelementille. Näin Netscape 4.x toimisi vanhanaikaisella HTML 3.2:n ohjauksella ja uudemmat selaimet modernimmalla CSS:n ohjauksella. Olen kuitenkin havainnut, että line-height ominaisuuden asettaminen ei aina auta saamaan haluttua lopputulosta Mozilla Gecko selaimissa (a test page[S]).

Edellä esittämäni ratkaisu ei kuitenkaan toimi MS IE 4.x Windows -selaimessa, sillä selain ei tue display:none taulukkoriveille. Jos Netscape 4.x:n tarvitsemat ylimääräiset rivit ja pastat skripteillä, dokumentti ei ole rakennettu aivan (X)HTML spesifikaatioiden mukaisesti. En löytänyt MS IE 4.x Windows -selaimille tekstilinkkejä käytettäessä täysin tyydyttävää ratkaisua. Jos valikoita tuotetaan lennosta JavaScript-koodauksella (kuten DHTML Menu Builder tekee), ne voivat olla erilaisia Netscape 4.x ja muille selaimille. Mutta valikoiden tuotattaminen skripteillä on sekin ongelmallista.

Optimaalisen tyylikäs ja parhaalla mahdollisella tavalla toimiva lopputulos MS IE 4.x Windows ja Netscape 4.x -selaimille saadaan ainoastaan silloin, kun kaikki linkit ovat kuvalinkkejä. En muuta kuitenkaan kaikkia linkkejä kuvalinkeiksi niiden vaatiman ylimääräisen työn vuoksi. Kuvalinkkien suosijan ei mielestäni kannata koodata sivuja käsin, vaikka TechsOfTheWeb.Com sivusto opettaa, miten kuvia voi käyttää dynaamisissa valikoissa. Koska MS IE 4.x ja Netscape 4.x käytetään suhteellisen vähän ja ne ovat sangen virheellisesti toimivia selaimia, en koe niiden täysipainoista huomioon ottamista mielekkääksi. Suosittelen koodieditoria käytettäessä tekstilinkkien käyttöä täytekuvin täydennettynä. Mielestäni ainoa järkevä vaihtoehto tälle on tehdä valikot kaupallisilla ohjelmilla kuten Macromedia Dreamweaver ja DHTML Menu Builder. Tosin huomautan vielä siitä, että em. ohjelmilla tehdyillä valikoilla esiintyy todennäköisesti ainakin joillakin selaimilla stabiliteettiongelmia.

Valikoiden ulkonäköä voi luoda tyylikkäämmäksi laittamalla niille aidosti tai näennäisesti läpinäkyviä valikoita tai varjoja.

Selainkohtaisia huomautuksia:

  1. Netscape 6.2+/ Mozilla 0.9.4+/ vähintään yhtä uusille muille Mozilla Gecko -selaimille saa CSS:llä aidosti läpinäkyvät hyvin toimivat teräväreunaiset valikot ja varjot -moz-opacity ominaisuuden avulla.

  2. Opera 6.x+ ja Safari (Mac) -selaimille saa hyvin toimivat puoliläpinäkyvät valikot ja varjot PNG-taustakuvilla (MS IE ei tue PNG-kuvissa läpinäkyvyyttä). (Mallikuva[S].)

  3. MS IE 5.5+ Windows -selaimille voi luoda läpinäkyviä valikoita ja pehmeäreunaisia varjoja epästandardia filter ominaisuutta käyttäen, mutta on huomattava, että MS IE 5.5:lle voi laittaa yhdelle elementille kerralla vain yhden efektin (linkki englanninkielisiin CSS-huomautuksiin[S]). Esim. pehmeät varjot voidaan luoda seuraavalla CSS:llä: filter:progid:DXImageTransform.Microsoft.Shadow(color='#777777', Direction=135, Strength=5);. Dynamic Drive:n kokoelmasta löytyy ZIP-tiedosto, josta löytyy filter ominaisuutta hyödyntävä mallivalikko (Top Navigational Bar IV). Valikossa on eräitä toimintaongelmia Opera kanssa, jotka olen maininnut aikaisemmalla jaksolla[S].

  4. Muille kuin uusille MS IE ja Mozilla Gecko -selaimille voi laittaa läpinäkyviä GIF-kuvia. Tietyt kuviot luovat karkeaa läpinäkyvyyttä.


Dynamic Drive: Top Navigational Bar IV; Macromedia; TecsOfTheWeb.Com: Using and Manipulating Dropdown Windows; xFX JumpStart: DHTML Menu Builder.

Selostan joitakin käyttöseikkoja myös selailuohjeissa[S] - suurimmalla osalla sivuista on pikalinkki tähän opastukseen (kysymysmerkki Apua).

[Alku]
   
Copyright Tapio Markula 1999-2003, Salo (kotisivu, s-posti - lisää s-postiosoiteeseen pisteellä erotettuna nimeni, Tapio Markula) (@dnainternet.net) - ei julkiskäyttöön ilman sopimusta.
Get Expression!
Editori, jolla saa luotua standardit täyttäviä HTML ja XML dokumentteja. Tämän sivuston sivut on useimmissa tapauksissa tarkastettu Dave Raggetin (W3C) tekemällä HTML-Tidy apuohjelmalla ja satunnaisesti W3C-organisaation virallisella koodintarkastusohjelmalla. Useimpien sivujen syntaksin pitäisi olla sopusoinnussa W3C:n XHTML 1.0 spesifikaation kanssa. Testaa tämä sivu!
Informaatiota selaimista, jotka näyttävät tai tulostavat tämän sivuston parhaiten.
[Hae Opera] [Hae Mozilla!]
CSS-opasta on viimeksi muutettu 20.12.2004