Pohyb myši:přejetí myší/ven, zadání myši/opuštění

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í (relatedTargettarget ).

Pro mouseout naopak:

  • event.target – je prvek, který myš opustila.
  • event.relatedTarget – je nový prvek pod ukazatelem, který myš ponechala (targetrelatedTarget ).

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 :

Resultscript.jsstyle.cssindex.html
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.

Resultscript.jsstyle.cssindex.html
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 #parentmouseover 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 :

  1. mouseout [target: parent] (odešel rodič), pak
  2. mouseover [target: child] (přišel k dítěti, zabublal).
Resultscript.jsstyle.cssindex.html
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:

  1. Přechody uvnitř prvku do/z potomků se nezapočítávají.
  2. 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.html
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" 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.html
table.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 ji currentElem .
  • 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:

  1. Používá delegování událostí ke zpracování vstupu/opuštění libovolného <td> uvnitř stolu. Spoléhá se tedy na mouseover/out místo mouseenter/leave které nevytvářejí bubliny, a proto neumožňují žádné delegování.
  2. Další události, jako je přesun mezi potomky <td> jsou odfiltrovány, takže onEnter/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 a mouseenter/leave mají další vlastnost:relatedTarget . To je prvek, ze kterého/do kterého přicházíme, komplementární k target .

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í.