dagblog.
← Archiv

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"&gt
<html&gt
<head&gt
<script language="JavaScript"&gt
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&gt
</head&gt
<body style="margin:20px 20px 20px 20px;"&gt
<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');"&gt

Outer DIV
<br /&gt<br /&gt
<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');"&gt

Inner DIV
</div&gt
</div&gt
<br /&gt
<input onclick="clearLog();" type="button" value="clear LOG" /&gt
<br /&gt
<textarea id="console"
style="width:500px;height:300px;"&gt</textarea&gt
</body&gt
</html&gt
Ilustrační obrázek
Archivní obrázek k článku Pořadí událostí v prohlížečích, snímek 1
Obrázek se nepodařilo načíst. Archivní obrázek k článku Pořadí událostí v prohlížečích, snímek 1
↗ Medium
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 over
Př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.

Verze na Medium

Související články

Související epizody CZ Podcastu