Dnes budeme dynamicky skrývat a zobrazovat prvky na stránce, ukážeme si rozdíly v použití vlastností visibility a display. Do DHTML knihovny přidáme nové funkce a na příkladech ukážeme jejich využití.
Zobrazování a skrývání prvků na stránce je vůbec nejčastějším využitím DHTML. Pomocí této techniky se vytvářejí všechny základní, často používané efekty v interaktivních HTML dokumentech - např. "rozbalování" menu či zobrazování nápovědy a podrobnějších informací po najetí myší. Nikdo by se neměl nechat zmýlit ani velmi efektní dynamičností obsahu stránek a myslet si, že prvky, které se objeví na stránce po nějaké akci, se v tu chvíli nějak vytvářejí či odněkud načítají. Ve většině případů již všechny informace jsou na svém místě již od načtení stránky - jsou pouze neviditelné. Činnost uživatele (najetí myší nad nějaký prvek, kliknutí, stisk klávesy atd.) pouze způsobí zviditelnění příslušné skupiny prvků na stránce a případně jinou skupinu zase skryje.
Při tvorbě dynamických stránek na ně proto nesmíte pohlížet stejnou optikou jako čtenáři, dívejte se na ně vždy jako programátor. Anebo, přesněji řečeno, jako kouzelník-iluzionista, jenž provádí trivální a jednoduché úkony, které však z pohledu diváků vypadají jako kouzla. Dynamické stránky se programují obdobně. Vy, jako jejich tvůrce jen připravíte vše, co na stránce má být, umístíte to na správná místa a patřičně nastylujete - pouze prvky, které mají dělat na stránce ono "kouzlo", skryjete a v pravou chvíli je jednoduchým příkazem odkryjete. Z pohledu diváka to pak ale vypadá, že se z přihrádek vysouvají položky menu a text článku, který tam předtím nebyl, se po kliknutí myší náhle zobrazí. Připravujme své dynamické stránky stejně jako iluzionista vymýšlí své triky - často ty nejefektnější věci uděláme tím nejprostším způsobem.
O událostech (events), jimiž se typicky dynamické akce na stránkách spouštějí, a o jejich vazbách se skripty si
povíme příště, dnes si připravíme základní funkce na práci s viditelností objektů a naučíme se s nimi pracovat. Pro zobrazování
a skrývání objektů se používají dvě vlastnosti CSS - visibility
a display
. Ačkoli pomocí obou
můžeme objekt na stránce "zneviditelnit", jejich chování se poněkud liší a má také rozdílné následky.
Visibility
může mít hodnoty 'visible'
[viditelný] nebo 'hidden'
[skrytý]
(a také 'inherit'
- převezme hodnotu z rodičovského prvku - a 'collapse'
- používá se pro políčka
tabulek). Výchozí hodnotou je typicky visible
, tzn. že prvek je viditelný a běžným způsobem umístěný ve stránce.
Pokud má hodnotu hidden
, stane se neviditelným; ve stránce však zůstane na svém místě a okolní prvky se chovají
stejně, jako by tento prvek byl viditelný. Dynamická změna této vlastnosti tedy nemá žádný vliv na formátování stránky
- změní-li se visibility
prvku na hidden
, prvek sice opticky zmizí, ale nezmění se formátování
stránky - ve stránce po něm zůstane "díra", stane se pouze zcela průhledným.
Vlastnost display
má naproti tomu odlišný význam - definuje, jakým způsobem se má prvek formátovat; zda jako
blok (hodnota 'block'
), jako úsek textu ('inline'
), "plovoucí" titulek ('run-in'
),
nebo jeden z mnoha dalších typů formátování (viz popis vlastnosti display).
Jednou z možných hodnot je hodnota 'none'
, která způsobí, že prvek se neformátuje nijak: vůbec se nezobrazí,
jakoby ani nebyl v kódu stránky uveden. Pokud dynamicky změníme hodnotu display
na none
, prvek
se ze stránky ztratí a celý dokument se znovu přeformátuje - resp. ty jeho části, které tento prvek nějakým způsobem ovlivňoval,
se změní tak, jako bychom náš "neviditelný" prvek ze stránky vyjmuli. Pokud tedy tímto způsobem "odstraníme"
ze stránky odstavec, zmizí a odstavce za ním následujcí se posunou výš; pokud odstraníme nějaký inline prvek (část
textu), odstavec, kde prvek ležel, se znovu zformátuje, jakoby v něm tento úsek nikdy nebyl.
Zde je vidět základní rozdíl mezi chováním display
a visibility
: když budeme peridicky měnit
visibility
prvku z visible
na hidden
a zpět, bude prvek na stránce "blikat",
nic víc se dít nebude. Pokud obdobně budeme měnit display
např. z block
na none
,
bude prvek ze stránky mizet a zase se v ní vykreslovat, přičemž se pokaždé celá stránka, nebo alespoň její část přeformátuje.
Při rychlých změnách by místo "blikání" nejspíš nastala jen nepřehledná změť obsahu stránky - stránka už by
se totiž nestíhala přeformátovávat.
Pro srovnání chování visibility
a display
se podívejte na ukázku.
V některých situacích může použití display
přinášet nevýhody a bude lepší dát přednost visibility
,
která nenutí stránku k překreslování a změna viditelnosti je tak rychlá. Ve většině případů však výhodnější použití display
.
Protože různé situace vyžadují různá řešení, ukažme si, kdy je která z obou možností vhodnější a jaké jsou případné výhody
i nevýhody:
display
. Skrytý úsek "zmizí"
ze stránky a po zobrazení se opět "vsune" na původní místo. Display
tedy použijeme na objekty,
které ovlivňují formátování okolních prvků - použili-li bychom visibility:hidden
, ve stránce by vznikla
"díra". Nepoužívejme však display
tehdy, je-li pro nás změna formátování stránky časově kritická
(především v animacích).display
- řešení s visibility
si můžeme
dovolit jen při dobrém rozmyslu. Umístění absolutně pozicovaných prvků ve stránce je sice nezávislé na okolí a po
skrytí objektu po prvku nemusí vzniknout žádná "díra" - je zde ale jeden háček: prvky ve stránce, i když
jsou neviditelné (visibility:hidden
), stále mohou reagovat na činnost uživatele. Stane se tak, že prvky
umístěné "pod" těmito skrytými objekty nezaregistrují pohyb či kliknutí myši, neboť tyto události
si přivlastní "výše" umístěné neviditelné objekty. Objekty skryté pomocí display:none
už ale
ve stránce vlastně nejsou a tento problém nezpůsobují. Skrývání pomocí visibility
tedy používáme jen
tehdy, pokud nebude vadit, když prvkům pod skrývanými objekty budou hůře přístupné události myši.<object>
/ <embed>
(především flash animace)
a prvky iframe je nutné vždy skrývat pomocí display:none
. Obsah těchto prvků (i když jsou "neviditelné")
bude vždy ve stránkách tropit neplechu: flash animace zůstanou aktivní, některé prvky ze stránek načtených do iframu
zůstanou viditelné atd. Zde se visibility
nedoporučuje používat vůbec.visibility
tak oceníme především v animacích - změna je rychlá (stránka se nemusí přeformátovat)
a zobrazení a skrytí prvků tak bude plynulejší a rychlejší. I zde je ale vhodné celou animaci skrýt pomocí display:none
,
aby nerušila chování stránky. Příkladem může být menu se složitou strukturou - skrývání a zobrazování nabídek a podnabídek
se z důvodů rychlosti může vytvořit pomocí visibility
, celé menu se však zobrazí a skryje pomocí display
- skryté nabídky tak nebudou rušit a ve stránce se objeví, až když se menu aktivuje. Po výběru položky se ze stránky
zase "ztratí".Je nutné si pamatovat také na pravidla dědičnosti, která se u vlastností visibility
a display
liší. Pokud má nějaký prvek display:none
, nezobrazí se ani on, ani nic z jeho obsahu - bez ohledu na hodnoty
display
u jeho potomků.
Kdežto u vlastnosti visibility
platí, že prvek, který ji má explicitně nastavenu, se řídí jen podle této hodnoty
- bez ohledu na viditelnost svého rodičovského prvku. Ukažme si to na příkladu:
<DIV id="obal"> <P id="prvni">první odstavec uvnitř</P> <P id="druhy" style="visibility:visible">druhý odstavec</P> <P id="treti">třetí odstavec</P> </DIV>
Takto definovaný blok se zobrazí přesně tak, jak bychom očekávali - uvnitř vnějšího <DIV>
budou zobrazeny
tři odstavce. Pokud však tento vnější obal skryjeme, tedy nastavíme mu visibility:hidden
, zneviditelní
se ("zprůsvitní") vnější blok a prvky uvnitř něj, které nemají definovánu vlastnost visiblity
(mají
tedy výchozí hodnotu inherit
a jejich viditelnost se řídí podle rodičovského prvku). Druhý odstavec však
má definováno visibility:visible
a bude tak viditelný bez ohledu na viditelnost svého rodičovského prvku
- podívejte se na ukázku. Změny vlastnosti display
takové chování nemají - pokud "obal" skryjeme pomocí display:none
, zmizí tento blok i jeho obsah,
bez ohledu na vlastnosti vnitřních prvků.
Minule jsme si již ujasnili, že v Netscape 4.x jsou vlastnosti týkající se
stylů pro DHTML zcela nepoužitelné (nelze je měnit po načtení stránky, pro dynamické akce se hodí pouze prvek <layer>
,
který je již "mrtvý"). Proto již můžeme s klidným svědomím opustit původní pokus o zcela univerzální DHTML knihovnu,
použitelnou ve všech prohlížečích. Omlouvám se tímto P. T. čtenářům za menší okliku: chtěl jsem se tak vyhnout výtkám,
že ignoruji ještě dožívající NN4 - dokud nebude vše náležitě vyjasněno a důvody ozřejmeny.
Nyní již víme, že jakákoli podpora DHTML funkcí pro NN4 by byla jen zdánlivá, skutečného použití by tyto snahy beztak nikdy nemohly dojít. Nadále budeme tedy pokračovat pouze s jedinou knihovnou, některá "neškodná" rozšíření oproti standardu DOM, která nás příliš nezatíží, v ní můžeme klidně ponechat - na podporu "nedynamického" NN4 však již rezignujeme.
Připravíme si funkce pro skrývání a zobrazování objektů pomocí vlastností, které jsme si výše vysvětlili. CSS vlastnosti
visibility
odpovídá v Javascriptu vlastnost Element
.style.visibility
, vlastnosti
display
pak Element
.style.display
; jejich hodnoty jsou shodné jako v CSS.
Funkci pro nastavení hodnot vlastností již máme odminula - teoreticky již teď můžeme použít např.:
objSetStyle (obj,'visibility','visible'); objSetStyle (obj,'visibility','hidden');
Není to však příliš praktické; při přípravě DHTML stránek je zbytečně komplikované používat pro tak časté akce, jako skrývání
a zobrazování objektů, tak složité funkce. Bude jednodušší připravit si specializovanou funkci, řekněme objShow
,
jejímiž parametry bude pouze objekt a booleovská hodnota, zda objekt má být vidět, či nikoli (true
=viditelný,
false
=neviditelný).
function objShow (obj,on) {
return objSetStyle(obj,'visibility',(on) ? 'visible':'hidden');
}
Zavoláme-li tedy např. objShow('jmeno',true)
, tato funkce pouze spustí objSetStyle
pro vlastnost
visibility
s hodnotou visible
(v případě true
), resp. hidden
(v případě
false
). Funkce vrací stejnou hodnotu jako objSetStyle
- true
/false
podle toho, zda se viditelnost objektu podařilo přiřadit.
U vlastnosti visibility
to bylo jednodušší v tom, že zde máme pouze dvě možné hodnoty (visible
/hidden
).
V případě display
to ale bude mírně ztíženo: jednoznačná je pouze hodnota pro skrytí (none
),
kdežto viditelný objekt může mít mít různou hodnotu display
(typicky block
nebo inline
,
ale můžeme potřebovat i mnoho jiných hodnot). Do další funkce (nazveme ji objDisplay
) přidáme proto třetí
parametr, kterým můžeme tuto "zviditelňovací" hodnotu upřesnit. Ale protože nejčastěji se pracuje s bloky (hodnota
block
), použijeme tuto hodnotu jako výchozí: pokud typ neupřesníme, použije se block
.
function objDisplay (obj,on,type) { if (on && !type) type = 'block';
return objSetStyle(obj,'display',(on) ? type:'none');
}
Tuto funkci tedy můžeme použít obdobně funkci první - zavolání objDisplay(objekt,false)
nastaví objektu display:none
,
naopak objDisplay(objekt,true)
nastaví display:block
. Pokud chceme jinou hodnotu než block
,
při zobrazování ji můžeme specifikovat - např. objDisplay(objekt,true,'inline')
.
Pozn.: Bystřejší čtenáři si jistě všimli, že tuto funkci můžeme použít i pro jiné změny vlastnosti display
- z bloku uděláme inline pomocí objDisplay(obj,true,'inline')
a naopak zase objDisplay(obj,true,'block')
(parametr 'block' zde můžeme vynechat, neboť je výchozí).
Pozn. 2: Hodnotou on
nemusí být nutně jen false
/true
; díky automatickému
přetypování v Javascriptu můžeme použít i hodnoty jiných typů, které se při testu if(on)
, resp. (on)
?
přetypují na příslušnou booleovskou hodnotu:
Můžeme proto použít i konstrukce např.:
var i = 0; objShow (obj,i); // i==0, skrytí objektu i++; objShow (obj,i); // i==1, zobrazení obejktu objDisplay (objX,0); objDisplay (objY,1,'inline'); objDisplay (objZ,''); objDisplay (objZ,'ukaz');
Naše nová (nyní již sloučená knihovna) tedy vypadá takto:
// Webtip.cz - DHTML knihovna // verze 0.5 function objGet(x) { if (typeof x != 'string') return x; else if (Boolean(document.getElementById)) return document.getElementById(x); else if (Boolean(document.all)) return eval('document.all.'+x); // pro MSIE 4 else return null; } function objSetStyle (obj,prop,val) { var o = objGet(obj); if (o && o.style) { eval ('o.style.'+prop+'="'+val+'"'); return true; } else return false; } function objShow (obj,on) { return objSetStyle(obj,'visibility',(on) ? 'visible':'hidden'); } function objDisplay (obj,on,type) { if (on && !type) type = 'block'; return objSetStyle(obj,'display',(on) ? type:'none'); } // Ceske ekvivalenty funkci: var objNajdi = objGet; var objNastavStyl = objSetStyle; var objZobraz = objShow;
Pro funkci objShow
jsme přidali český ekvivalent objZobraz
, funkci objDisplay
nemá
význam překládat.
Ač naše knihovna není zatím příliš obsáhlá a možná se to ani nezdá, nyní již máme základní nástroje pro DHTML. S funkcemi pro nalezení objektů, nastavení jejich CSS vlastností a nástroji pro změnu viditelnosti již uděláme nějakou tu " muziku za málo peněz" - jediné, co ještě potřebujeme, je umět pracovat s událostmi, tedy provést nějakou akci, když uživatel klikne myší či najede kurzorem na nějaký prvek, stiskne klávesu, načte se stránka atd. O nich si povíme příště. Na některé jednoduché příklady se ale můžete podívat už teď.
Někteří z vás už se s tím možná setkali, jiní třeba ještě ne - chcete si přečíst nějakou stránku na webu, ale váš prohlížeč zde zahlásí chybu Javascriptu (nebo ani to ne) a nefungují žádné aktivní prvky. Nelze otevřít menu, nefungují odkazy, obsah je skrytý, nedostane se k němu. Stát se to může kdykoli a komukoli - autor udělá ve skriptu chybu a nevšimne si jí, čtenář má "neobvyklý" prohlížeč, nemá podporu Javascriptu nebo si jej (z jakéhokoli důvodu) vypnul atd. Tak jako tak, stránka se stala naprosto nepoužitelnou, její obsah je pro (tohoto) čtenáře nedostupný. I výše uvedená ukázka je (úmyslně!) taková - stačí se na ni podívat pomocí prohlížeče Opera. Uvidíte pouze "zabalené" položky menu a nadpisy, ale k jejich obsahu se nedostanete.
Obsah stránek je přitom to hlavní, co na nich je (až na nepatrné, konkrétně zdůvodnitelné výjimky) - to, co chcete svým
čtenářům poskytnout především. Všechno ostatní (vzhled, barvy, dynamika) by už mělo být jen "třešničkami na dortu",
které můžete dát jen tomu, kdo je dokáže použít, případně kdo o ně stojí. Stránka by tak měla fungovat dostatečně kdekoli,
v každém rozlišení, s jakýmkoli nastavením, s vypnutými CSS, či bez Javascriptu. Dáváte svým čtenářům obsah stránek, proto
všechna rozšíření nad jeho rámec udělejte tak, aby byla volitelná či nepovinná. V případě skrývání obsahu např. pomocí
display:none
je tedy správným postupem skrýt ho pouze tehdy, je-li jisté, že čtenářův prohlížeč má funkční
Javascript (JS), který obsah určitě dokáže zase zobrazit. Možností je více, nejčastější postupy jsou:
display
) a tudíž je bude moci zase zobrazit.Ukázka 1 - srovnání použití display a visibility
Ukázka 2 - dědičnost visibility
Ukázka 3 - jednoduché příklady použití skrývání a zobrazování
pomocí naší knihovny
Element.style.visibility
layer.visibility
Element.style.display
Číslo verze: | 0.5 (pro přehlednost číslujeme verze shodně s díly seriálu) |
Stažení knihovny: | dhtml_0_5.js |
Obsah (anglické názvy) | objGet() , objSetStyle() , objShow() , objDisplay() |
Obsah (české názvy) | objNajdi() , objNastavStyl() , objZobraz() |
Petr Staníček, pixy.cz © 2002, 2015