Pořadí událostí v prohlížečích
Rád bych se s Vámi podělil o velmi zajímavou věc. Programuji pro třívrstvou aplikaci prezentační vrstvu webu a narazil jsem na problém s eventami
v prohlížečích. Potřeboval jsem vytvořit za pomoci HTML a JS popup kalendář. Chci aby se choval následovně: Na stránce je malý button. Když na něj user klikne
zobrazí se absolutně pozicovaný DIV s kalendářem, který je zobrazen dokud je user ukazatelem myši
nad kalendářem nebo nad tlačítkem vyvolávajícím kalendář.
To znamená, že na událost onmouseout těchto dvou prvku zavolám JS funkci a ta skryje DIV s kalendářem. Všechno by krásně fungovalo, kdyby ten
inkriminovaný DIV neměl v sobě vnořené další elementy (tlačítko pro výběr měsíce, jednotlivé dny….)
Nejlépe to předvedu na příkladu:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><script language="JavaScript">
var logID = 0;
function addLog(message) {
var log = document.getElementById("console");
logID++;
log.value = log.value + logID + " : " + message + "\n"
}
function clearLog(){
var log = document.getElementById("console");
log.value = "";
logID = 0;
}
</script></head>
<body style="margin:20px 20px 20px 20px;">
<div id="outter" align="center" style="border:1px solid black;
background-color:#AAAAff;width:100px;height:100px"
onmouseover="addLog('outer DIV - mouse over');"
onmouseout="addLog('outer DIV - mouse out');">
Outer DIV
<br /><br />
<div style="border:1px solid black;
background-color:#AAFFAA;width:50px;height:50px;margin:auto;"
onmouseover="addLog('inner DIV - mouse over');"
onmouseout="addLog('inner DIV - mouse out');">
Inner DIV
</div>
</div>
<br />
<input onclick="clearLog();" type="button" value="clear LOG" />
<br />
<textarea id="console"
style="width:500px;height:300px;"></textarea>
</body>
</html>Ilustrační obrázek

Nyní si projdeme události jak jsou vyvolávány když hýbeme myší podle
červené šipky v obrázku:
1 : outer DIV - mouse over
2 : outer DIV - mouse out
3 : inner DIV - mouse over
4 : outer DIV - mouse overPřekvapivé jsou eventy 2 a 4. Zvláště eventa 2 nám znemožňuje na událost onmouseout outterDivu skrýt outterDiv.
Můj původní předpoklad byl, že se eventy chovají tak, že outter mouse over a outter mouse out se vyvolá pouze
v případě, že myší najedu a nebo sjedu z tohoto divu avšak jeho "děti/vnořené elementy" nikdy nevyvolají tyto eventy
u svého "rodiče/nadřazeného elementu". Nalezl jsem zatím dvě řešení problému.
První řešení
//JavaScript
var mysNadDiv = false;
var delayCallID = 0;
function delayCall(funcCall, delay){
clearTimeout(delayCallID);
delayCallID = setTimeout(funcCall,delay);
}
function hideDiv(){
if (!mysNadDiv) {
document.getElementById('outter').style.display="none";
}
}//do html k outter divu
onmouseover="mysNadDiv=true;"
onmouseout="mysNadDiv=false;delayCall('hideDiv();',200);"Jde v podstatě o zpožděné zavolání funkce v JS při eventě 2 a než se skutečně zavolá hideDiv tak mezitím
eventa 4 znemožní skrytí přes proměnou 'mysNadDiv'. Ve výsledku se outter Div skryje jen když opravdu myš opustí outter Div.
clearTimeout je v JS funkci proto, aby se nekumulovalo zbytečně více timerů při rychlém přejíždění myši.
Druhé řešení
Hlídat si pozici myši a vykašlat se na eventy. Outter Div skrýt jen tehdy, když se souřadnice myši dostanou
mimo definovanou oblast outer Divem.
Jestli někdo zná lepší řešení, sem s ním. Jen bych rád podotknul, že inner Divů může být klidně 100 a v každém inner Divu
můžou být další vnořené elementy a musí Vámi navrhnuté řešení stále fungovat s pokud možno nejméně přidaného kódu.
Související články
Související epizody CZ Podcastu
- #217 · Ivo Lukačovič
O Windy, JavaScriptu a budování firem.
- #3 · Java 6 SE, Vývoj webových aplikací
Dagi a Filemon o novinkách v Javě 6 a webových frameworcích.