Pojďme se ponořit do podrobností o událostech, ke kterým dochází, když se myš pohybuje mezi prvky.
Události přejetí myší/přejetí myší, související cíl
mouseover
událost nastane, když ukazatel myši najede na prvek, a mouseout
– když odejde.
Tyto události jsou speciální, protože mají vlastnost relatedTarget
. Tato vlastnost doplňuje target
. Když myš opustí jeden prvek jinému, jeden z nich se změní na target
a druhý – relatedTarget
.
Pro mouseover
:
event.target
– je prvek, na který se myš dostala.event.relatedTarget
– je prvek, ze kterého myš pochází (relatedTarget
→target
).
Pro mouseout
naopak:
event.target
– je prvek, který myš opustila.event.relatedTarget
– je nový prvek pod ukazatelem, který myš ponechala (target
→relatedTarget
).
V níže uvedeném příkladu jsou každá plocha a její prvky samostatné prvky. Když pohnete myší, můžete vidět události myši v textové oblasti.
Každá událost obsahuje informace o obou target
a relatedTarget
:
container.onmouseover = container.onmouseout = handler;
function handler(event) {
function str(el) {
if (!el) return "null"
return el.className || el.tagName;
}
log.value += event.type + ': ' +
'target=' + str(event.target) +
', relatedTarget=' + str(event.relatedTarget) + "\n";
log.scrollTop = log.scrollHeight;
if (event.type == 'mouseover') {
event.target.style.background = 'pink'
}
if (event.type == 'mouseout') {
event.target.style.background = ''
}
}
body,
html {
margin: 0;
padding: 0;
}
#container {
border: 1px solid brown;
padding: 10px;
width: 330px;
margin-bottom: 5px;
box-sizing: border-box;
}
#log {
height: 120px;
width: 350px;
display: block;
box-sizing: border-box;
}
[class^="smiley-"] {
display: inline-block;
width: 70px;
height: 70px;
border-radius: 50%;
margin-right: 20px;
}
.smiley-green {
background: #a9db7a;
border: 5px solid #92c563;
position: relative;
}
.smiley-green .left-eye {
width: 18%;
height: 18%;
background: #84b458;
position: relative;
top: 29%;
left: 22%;
border-radius: 50%;
float: left;
}
.smiley-green .right-eye {
width: 18%;
height: 18%;
border-radius: 50%;
position: relative;
background: #84b458;
top: 29%;
right: 22%;
float: right;
}
.smiley-green .smile {
position: absolute;
top: 67%;
left: 16.5%;
width: 70%;
height: 20%;
overflow: hidden;
}
.smiley-green .smile:after,
.smiley-green .smile:before {
content: "";
position: absolute;
top: -50%;
left: 0%;
border-radius: 50%;
background: #84b458;
height: 100%;
width: 97%;
}
.smiley-green .smile:after {
background: #84b458;
height: 80%;
top: -40%;
left: 0%;
}
.smiley-yellow {
background: #eed16a;
border: 5px solid #dbae51;
position: relative;
}
.smiley-yellow .left-eye {
width: 18%;
height: 18%;
background: #dba652;
position: relative;
top: 29%;
left: 22%;
border-radius: 50%;
float: left;
}
.smiley-yellow .right-eye {
width: 18%;
height: 18%;
border-radius: 50%;
position: relative;
background: #dba652;
top: 29%;
right: 22%;
float: right;
}
.smiley-yellow .smile {
position: absolute;
top: 67%;
left: 19%;
width: 65%;
height: 14%;
background: #dba652;
overflow: hidden;
border-radius: 8px;
}
.smiley-red {
background: #ee9295;
border: 5px solid #e27378;
position: relative;
}
.smiley-red .left-eye {
width: 18%;
height: 18%;
background: #d96065;
position: relative;
top: 29%;
left: 22%;
border-radius: 50%;
float: left;
}
.smiley-red .right-eye {
width: 18%;
height: 18%;
border-radius: 50%;
position: relative;
background: #d96065;
top: 29%;
right: 22%;
float: right;
}
.smiley-red .smile {
position: absolute;
top: 57%;
left: 16.5%;
width: 70%;
height: 20%;
overflow: hidden;
}
.smiley-red .smile:after,
.smiley-red .smile:before {
content: "";
position: absolute;
top: 50%;
left: 0%;
border-radius: 50%;
background: #d96065;
height: 100%;
width: 97%;
}
.smiley-red .smile:after {
background: #d96065;
height: 80%;
top: 60%;
left: 0%;
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="container">
<div class="smiley-green">
<div class="left-eye"></div>
<div class="right-eye"></div>
<div class="smile"></div>
</div>
<div class="smiley-yellow">
<div class="left-eye"></div>
<div class="right-eye"></div>
<div class="smile"></div>
</div>
<div class="smiley-red">
<div class="left-eye"></div>
<div class="right-eye"></div>
<div class="smile"></div>
</div>
</div>
<textarea id="log">Events will show up here!
</textarea>
<script src="script.js"></script>
</body>
</html>
relatedTarget
může být null
relatedTarget
vlastnost může být null
.
To je normální a znamená to, že myš nepřišla z jiného prvku, ale z okna. Nebo že to opustilo okno.
Tuto možnost bychom měli mít na paměti při použití event.relatedTarget
v našem kódu. Pokud přistoupíme na event.relatedTarget.tagName
, pak dojde k chybě.
Přeskočení prvků
mousemove
událost se spustí při pohybu myši. To však neznamená, že každý pixel vede k události.
Prohlížeč čas od času kontroluje polohu myši. A pokud zaznamená změny, spustí události.
To znamená, že pokud návštěvník pohybuje myší velmi rychle, mohou být některé prvky DOM přeskočeny:
Pokud se myš pohybuje velmi rychle od #FROM
na #TO
prvky, jak je nakresleno výše, pak střední <div>
prvky (nebo některé z nich) mohou být přeskočeny. mouseout
událost se může spustit na #FROM
a poté okamžitě mouseover
na #TO
.
To je dobré pro výkon, protože tam může být mnoho mezilehlých prvků. Ve skutečnosti nechceme zpracovávat a zpracovávat každý z nich.
Na druhou stranu bychom měli mít na paměti, že ukazatel myši „nenavštíví“ všechny prvky na cestě. Může „skákat“.
Zejména je možné, že ukazatel skočí přímo doprostřed stránky z okna. V tom případě relatedTarget
je null
, protože to přišlo „odnikud“:
Můžete se na to podívat „naživo“ na níže uvedeném testovacím stojanu.
Jeho HTML má dva vnořené prvky:<div id="child">
je uvnitř <div id="parent">
. Pokud na ně rychle přejedete myší, pak možná události spouští pouze podřízený div, nebo možná nadřazený, nebo možná nebudou žádné události.
Přesuňte také ukazatel do podřízeného prvku div
a pak jej rychle přesuňte dolů přes nadřazený. Pokud je pohyb dostatečně rychlý, rodičovský prvek je ignorován. Myš překročí nadřazený prvek, aniž by si toho všimla.
let parent = document.getElementById('parent');
parent.onmouseover = parent.onmouseout = parent.onmousemove = handler;
function handler(event) {
let type = event.type;
while (type.length < 11) type += ' ';
log(type + " target=" + event.target.id)
return false;
}
function clearText() {
text.value = "";
lastMessage = "";
}
let lastMessageTime = 0;
let lastMessage = "";
let repeatCounter = 1;
function log(message) {
if (lastMessageTime == 0) lastMessageTime = new Date();
let time = new Date();
if (time - lastMessageTime > 500) {
message = '------------------------------\n' + message;
}
if (message === lastMessage) {
repeatCounter++;
if (repeatCounter == 2) {
text.value = text.value.trim() + ' x 2\n';
} else {
text.value = text.value.slice(0, text.value.lastIndexOf('x') + 1) + repeatCounter + "\n";
}
} else {
repeatCounter = 1;
text.value += message + "\n";
}
text.scrollTop = text.scrollHeight;
lastMessageTime = time;
lastMessage = message;
}
#parent {
background: #99C0C3;
width: 160px;
height: 120px;
position: relative;
}
#child {
background: #FFDE99;
width: 50%;
height: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
textarea {
height: 140px;
width: 300px;
display: block;
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="parent">parent
<div id="child">child</div>
</div>
<textarea id="text"></textarea>
<input onclick="clearText()" value="Clear" type="button">
<script src="script.js"></script>
</body>
</html>
Pokud mouseover
spuštěno, musí být mouseout
V případě rychlých pohybů myši mohou být mezilehlé prvky ignorovány, ale jednu věc víme jistě:pokud ukazatel „oficiálně“ zadal prvek (mouseover
událost vygenerována), pak při opuštění vždy dostaneme mouseout
.
Vysunutí myši při odchodu pro dítě
Důležitá vlastnost mouseout
– spouští se, když se ukazatel přesune z prvku na jeho potomka, např. z #parent
na #child
v tomto HTML:
<div id="parent">
<div id="child">...</div>
</div>
Pokud jsme na #parent
a poté přesuňte ukazatel hlouběji do #child
, dostaneme mouseout
na #parent
!
To se může zdát divné, ale lze to snadno vysvětlit.
Podle logiky prohlížeče může být kurzor myši pouze nad jednou prvek kdykoli – nejvíce vnořený a nejvyšší podle z-indexu.
Pokud tedy přejde na jiný prvek (dokonce i na potomka), opustí předchozí.
Všimněte si prosím dalšího důležitého detailu zpracování události.
mouseover
událost na potomkovi probublá. Pokud tedy #parent
má mouseover
handler, spouští:
Velmi dobře to vidíte na níže uvedeném příkladu:<div id="child">
je uvnitř <div id="parent">
. Existuje mouseover/out
handlery na #parent
prvek, který vypíše podrobnosti o události.
Pokud pohnete myší z #parent
na #child
, uvidíte dvě události na #parent
:
mouseout [target: parent]
(odešel rodič), pakmouseover [target: child]
(přišel k dítěti, zabublal).
function mouselog(event) {
let d = new Date();
text.value += `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()} | ${event.type} [target: ${event.target.id}]\n`.replace(/(:|^)(\d\D)/, '$10$2');
text.scrollTop = text.scrollHeight;
}
#parent {
background: #99C0C3;
width: 160px;
height: 120px;
position: relative;
}
#child {
background: #FFDE99;
width: 50%;
height: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
textarea {
height: 140px;
width: 300px;
display: block;
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="parent" onmouseover="mouselog(event)" onmouseout="mouselog(event)">parent
<div id="child">child</div>
</div>
<textarea id="text"></textarea>
<input type="button" onclick="text.value=''" value="Clear">
<script src="script.js"></script>
</body>
</html>
Jak je znázorněno, když se ukazatel přesune z #parent
prvek na #child
, spouštějí se dva obslužné rutiny na nadřazeném prvku:mouseout
a mouseover
:
parent.onmouseout = function(event) {
/* event.target: parent element */
};
parent.onmouseover = function(event) {
/* event.target: child element (bubbled) */
};
Pokud neprozkoumáme event.target
uvnitř ovladačů, pak se může zdát, že ukazatel myši vlevo #parent
prvek a poté se přes něj okamžitě vrátil.
Ale není tomu tak! Ukazatel je stále nad nadřazeným prvkem, jen se posunul hlouběji do podřízeného prvku.
Pokud při opuštění nadřazeného prvku proběhnou nějaké akce, např. animace běží v parent.onmouseout
, obvykle to nechceme, když ukazatel jde hlouběji do #parent
.
Abychom tomu zabránili, můžeme zkontrolovat relatedTarget
v handleru a pokud je myš stále uvnitř prvku, pak takovou událost ignorujte.
Alternativně můžeme použít jiné události:mouseenter
a mouseleave
, které nyní pokryjeme, protože takové problémy nemají.
Události mouseenter a mouseleave
Události mouseenter/mouseleave
jsou jako mouseover/mouseout
. Spustí se, když ukazatel myši vstoupí do prvku nebo jej opustí.
Jsou tu ale dva důležité rozdíly:
- Přechody uvnitř prvku do/z potomků se nezapočítávají.
- Události
mouseenter/mouseleave
nebublá.
Tyto události jsou extrémně jednoduché.
Když ukazatel zadá prvek – mouseenter
spouštěče. Na přesném umístění ukazatele uvnitř prvku nebo jeho potomků nezáleží.
Když ukazatel opustí prvek – mouseleave
spouštěče.
Tento příklad je podobný výše uvedenému, ale nyní má horní prvek mouseenter/mouseleave
místo mouseover/mouseout
.
Jak vidíte, jediné generované události jsou ty, které souvisejí s přesunem ukazatele dovnitř a ven z horního prvku. Když ukazatel směřuje k dítěti a zpět, nic se nestane. Přechody mezi potomky jsou ignorovány
Resultscript.jsstyle.cssindex.htmlfunction mouselog(event) {
let d = new Date();
text.value += `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()} | ${event.type} [target: ${event.target.id}]\n`.replace(/(:|^)(\d\D)/, '$10$2');
text.scrollTop = text.scrollHeight;
}
#parent {
background: #99C0C3;
width: 160px;
height: 120px;
position: relative;
}
#child {
background: #FFDE99;
width: 50%;
height: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
textarea {
height: 140px;
width: 300px;
display: block;
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="parent" onmouseenter="mouselog(event)" onmouseleave="mouselog(event)">parent
<div id="child">child</div>
</div>
<textarea id="text"></textarea>
<input type="button" onclick="text.value=''" value="Clear">
<script src="script.js"></script>
</body>
</html>
Delegování události
Události mouseenter/leave
jsou velmi jednoduché a snadno použitelné. Ale nebublají. Nemůžeme tedy u nich používat delegování událostí.
Představte si, že chceme ovládat vstup/opuštění myší pro buňky tabulky. A jsou to stovky buněk.
Přirozeným řešením by bylo – nastavit handler na <table>
a zpracovávat tam události. Ale mouseenter/leave
nebublat. Pokud se taková událost stane na <td>
, pak pouze handler na tomto <td>
je schopen to chytit.
Obslužné nástroje pro mouseenter/leave
na <table>
spustí se pouze tehdy, když ukazatel vstoupí/opustí tabulku jako celek. Není možné v něm získat žádné informace o přechodech.
Použijme tedy mouseover/mouseout
.
Začněme jednoduchými ovladači, které zvýrazní prvek pod myší:
// let's highlight an element under the pointer
table.onmouseover = function(event) {
let target = event.target;
target.style.background = 'pink';
};
table.onmouseout = function(event) {
let target = event.target;
target.style.background = '';
};
Tady jsou v akci. Když se myš pohybuje přes prvky této tabulky, aktuální se zvýrazní:
Resultscript.jsstyle.cssindex.htmltable.onmouseover = function(event) {
let target = event.target;
target.style.background = 'pink';
text.value += `over -> ${target.tagName}\n`;
text.scrollTop = text.scrollHeight;
};
table.onmouseout = function(event) {
let target = event.target;
target.style.background = '';
text.value += `out <- ${target.tagName}\n`;
text.scrollTop = text.scrollHeight;
};
#text {
display: block;
height: 100px;
width: 456px;
}
#table th {
text-align: center;
font-weight: bold;
}
#table td {
width: 150px;
white-space: nowrap;
text-align: center;
vertical-align: bottom;
padding-top: 5px;
padding-bottom: 12px;
cursor: pointer;
}
#table .nw {
background: #999;
}
#table .n {
background: #03f;
color: #fff;
}
#table .ne {
background: #ff6;
}
#table .w {
background: #ff0;
}
#table .c {
background: #60c;
color: #fff;
}
#table .e {
background: #09f;
color: #fff;
}
#table .sw {
background: #963;
color: #fff;
}
#table .s {
background: #f60;
color: #fff;
}
#table .se {
background: #0c3;
color: #fff;
}
#table .highlight {
background: red;
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<table id="table">
<tr>
<th colspan="3"><em>Bagua</em> Chart: Direction, Element, Color, Meaning</th>
</tr>
<tr>
<td class="nw"><strong>Northwest</strong>
<br>Metal
<br>Silver
<br>Elders
</td>
<td class="n"><strong>North</strong>
<br>Water
<br>Blue
<br>Change
</td>
<td class="ne"><strong>Northeast</strong>
<br>Earth
<br>Yellow
<br>Direction
</td>
</tr>
<tr>
<td class="w"><strong>West</strong>
<br>Metal
<br>Gold
<br>Youth
</td>
<td class="c"><strong>Center</strong>
<br>All
<br>Purple
<br>Harmony
</td>
<td class="e"><strong>East</strong>
<br>Wood
<br>Blue
<br>Future
</td>
</tr>
<tr>
<td class="sw"><strong>Southwest</strong>
<br>Earth
<br>Brown
<br>Tranquility
</td>
<td class="s"><strong>South</strong>
<br>Fire
<br>Orange
<br>Fame
</td>
<td class="se"><strong>Southeast</strong>
<br>Wood
<br>Green
<br>Romance
</td>
</tr>
</table>
<textarea id="text"></textarea>
<input type="button" onclick="text.value=''" value="Clear">
<script src="script.js"></script>
</body>
</html>
V našem případě bychom rádi zvládli přechody mezi buňkami tabulky <td>
:vstup do buňky a její opuštění. Jiné přechody, například uvnitř buňky nebo vně jakékoli buňky, nás nezajímají. Pojďme je odfiltrovat.
Zde je to, co můžeme udělat:
- Pamatujte si aktuálně zvýrazněný
<td>
v proměnné, nazvěme jicurrentElem
. - Na
mouseover
– ignorovat událost, pokud jsme stále uvnitř aktuálního<td>
. - Na
mouseout
– ignorovat, pokud jsme nezanechali aktuální<td>
.
Zde je příklad kódu, který zohledňuje všechny možné situace:
// <td> under the mouse right now (if any)
let currentElem = null;
table.onmouseover = function(event) {
// before entering a new element, the mouse always leaves the previous one
// if currentElem is set, we didn't leave the previous <td>,
// that's a mouseover inside it, ignore the event
if (currentElem) return;
let target = event.target.closest('td');
// we moved not into a <td> - ignore
if (!target) return;
// moved into <td>, but outside of our table (possible in case of nested tables)
// ignore
if (!table.contains(target)) return;
// hooray! we entered a new <td>
currentElem = target;
onEnter(currentElem);
};
table.onmouseout = function(event) {
// if we're outside of any <td> now, then ignore the event
// that's probably a move inside the table, but out of <td>,
// e.g. from <tr> to another <tr>
if (!currentElem) return;
// we're leaving the element – where to? Maybe to a descendant?
let relatedTarget = event.relatedTarget;
while (relatedTarget) {
// go up the parent chain and check – if we're still inside currentElem
// then that's an internal transition – ignore it
if (relatedTarget == currentElem) return;
relatedTarget = relatedTarget.parentNode;
}
// we left the <td>. really.
onLeave(currentElem);
currentElem = null;
};
// any functions to handle entering/leaving an element
function onEnter(elem) {
elem.style.background = 'pink';
// show that in textarea
text.value += `over -> ${currentElem.tagName}.${currentElem.className}\n`;
text.scrollTop = 1e6;
}
function onLeave(elem) {
elem.style.background = '';
// show that in textarea
text.value += `out <- ${elem.tagName}.${elem.className}\n`;
text.scrollTop = 1e6;
}
Ještě jednou, důležité funkce jsou:
- Používá delegování událostí ke zpracování vstupu/opuštění libovolného
<td>
uvnitř stolu. Spoléhá se tedy namouseover/out
místomouseenter/leave
které nevytvářejí bubliny, a proto neumožňují žádné delegování. - Další události, jako je přesun mezi potomky
<td>
jsou odfiltrovány, takžeonEnter/Leave
běží pouze v případě, že ukazatel opustí nebo vstoupí do<td>
jako celek.
Zde je úplný příklad se všemi podrobnostmi:
Resultscript.jsstyle.cssindex.html// <td> under the mouse right now (if any)
let currentElem = null;
table.onmouseover = function(event) {
// before entering a new element, the mouse always leaves the previous one
// if currentElem is set, we didn't leave the previous <td>,
// that's a mouseover inside it, ignore the event
if (currentElem) return;
let target = event.target.closest('td');
// we moved not into a <td> - ignore
if (!target) return;
// moved into <td>, but outside of our table (possible in case of nested tables)
// ignore
if (!table.contains(target)) return;
// hooray! we entered a new <td>
currentElem = target;
onEnter(currentElem);
};
table.onmouseout = function(event) {
// if we're outside of any <td> now, then ignore the event
// that's probably a move inside the table, but out of <td>,
// e.g. from <tr> to another <tr>
if (!currentElem) return;
// we're leaving the element – where to? Maybe to a descendant?
let relatedTarget = event.relatedTarget;
while (relatedTarget) {
// go up the parent chain and check – if we're still inside currentElem
// then that's an internal transition – ignore it
if (relatedTarget == currentElem) return;
relatedTarget = relatedTarget.parentNode;
}
// we left the <td>. really.
onLeave(currentElem);
currentElem = null;
};
// any functions to handle entering/leaving an element
function onEnter(elem) {
elem.style.background = 'pink';
// show that in textarea
text.value += `over -> ${currentElem.tagName}.${currentElem.className}\n`;
text.scrollTop = 1e6;
}
function onLeave(elem) {
elem.style.background = '';
// show that in textarea
text.value += `out <- ${elem.tagName}.${elem.className}\n`;
text.scrollTop = 1e6;
}
#text {
display: block;
height: 100px;
width: 456px;
}
#table th {
text-align: center;
font-weight: bold;
}
#table td {
width: 150px;
white-space: nowrap;
text-align: center;
vertical-align: bottom;
padding-top: 5px;
padding-bottom: 12px;
cursor: pointer;
}
#table .nw {
background: #999;
}
#table .n {
background: #03f;
color: #fff;
}
#table .ne {
background: #ff6;
}
#table .w {
background: #ff0;
}
#table .c {
background: #60c;
color: #fff;
}
#table .e {
background: #09f;
color: #fff;
}
#table .sw {
background: #963;
color: #fff;
}
#table .s {
background: #f60;
color: #fff;
}
#table .se {
background: #0c3;
color: #fff;
}
#table .highlight {
background: red;
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<table id="table">
<tr>
<th colspan="3"><em>Bagua</em> Chart: Direction, Element, Color, Meaning</th>
</tr>
<tr>
<td class="nw"><strong>Northwest</strong>
<br>Metal
<br>Silver
<br>Elders
</td>
<td class="n"><strong>North</strong>
<br>Water
<br>Blue
<br>Change
</td>
<td class="ne"><strong>Northeast</strong>
<br>Earth
<br>Yellow
<br>Direction
</td>
</tr>
<tr>
<td class="w"><strong>West</strong>
<br>Metal
<br>Gold
<br>Youth
</td>
<td class="c"><strong>Center</strong>
<br>All
<br>Purple
<br>Harmony
</td>
<td class="e"><strong>East</strong>
<br>Wood
<br>Blue
<br>Future
</td>
</tr>
<tr>
<td class="sw"><strong>Southwest</strong>
<br>Earth
<br>Brown
<br>Tranquility
</td>
<td class="s"><strong>South</strong>
<br>Fire
<br>Orange
<br>Fame
</td>
<td class="se"><strong>Southeast</strong>
<br>Wood
<br>Green
<br>Romance
</td>
</tr>
</table>
<textarea id="text"></textarea>
<input type="button" onclick="text.value=''" value="Clear">
<script src="script.js"></script>
</body>
</html>
Pokuste se přesunout kurzor dovnitř a ven z buněk tabulky a uvnitř nich. Rychle nebo pomalu – na tom nezáleží. Pouze <td>
jako celek je zvýrazněn, na rozdíl od předchozího příkladu.
Shrnutí
Zabývali jsme se událostmi mouseover
, mouseout
, mousemove
, mouseenter
a mouseleave
.
Je dobré si uvědomit tyto věci:
- Rychlý pohyb myši může přeskočit přechodné prvky.
- Události
mouseover/out
amouseenter/leave
mají další vlastnost:relatedTarget
. To je prvek, ze kterého/do kterého přicházíme, komplementární ktarget
.
Události mouseover/out
spouště, i když přejdeme z rodičovského prvku na podřízený prvek. Prohlížeč předpokládá, že myš může být v jednu chvíli pouze nad jedním prvkem – nad tím nejhlubším.
Události mouseenter/leave
se v tomto aspektu liší:spouštějí se pouze tehdy, když myš vstoupí a vyjede z prvku jako celku. Také nebublají.