Ponořme se nyní do dalších detailů událostí, které nastávají, když se ukazatel myši pohybuje mezi elementy.
Události mouseover/mouseout, relatedTarget
Událost mouseover nastává, když ukazatel myši vstoupí na element, a mouseout nastane, když jej opustí.
Tyto události jsou speciální v tom, že mají vlastnost relatedTarget, která doplňuje vlastnost target. Když se ukazatel přesune z jednoho elementu na druhý, jeden z nich se stane hodnotou target a druhý hodnotou relatedTarget.
Pro mouseover:
událost.target– je element, na který ukazatel vstoupil.event.relatedTarget– je element, ze kterého ukazatel přišel (relatedTarget→target).
Pro mouseout je to obráceně:
event.target– je element, který ukazatel opustil.event.relatedTarget– je nový element pod ukazatelem, na který ukazatel vstoupil (target→relatedTarget).
V následujícím příkladu jsou každá tvář i její jednotlivé prvky samostatné elementy. Když budete pohybovat myší, uvidíte v textové oblasti události myši.
Každá událost obsahuje informaci o target i o relatedTarget:
kontejner.onmouseover = kontejner.onmouseout = handler;
function handler(událost) {
function str(el) {
if (!el) return "null"
return el.className || el.tagName;
}
log.value += událost.type + ': ' +
'target=' + str(událost.target) +
', relatedTarget=' + str(událost.relatedTarget) + "\n";
log.scrollTop = log.scrollHeight;
if (událost.type == 'mouseover') {
událost.target.style.background = 'pink'
}
if (událost.type == 'mouseout') {
událost.target.style.background = ''
}
}body,
html {
margin: 0;
padding: 0;
}
#kontejner {
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^="smajlík-"] {
display: inline-block;
width: 70px;
height: 70px;
border-radius: 50%;
margin-right: 20px;
}
.smajlík-zelený {
background: #a9db7a;
border: 5px solid #92c563;
position: relative;
}
.smajlík-zelený .levé-oko {
width: 18%;
height: 18%;
background: #84b458;
position: relative;
top: 29%;
left: 22%;
border-radius: 50%;
float: left;
}
.smajlík-zelený .pravé-oko {
width: 18%;
height: 18%;
border-radius: 50%;
position: relative;
background: #84b458;
top: 29%;
right: 22%;
float: right;
}
.smajlík-zelený .úsměv {
position: absolute;
top: 67%;
left: 16.5%;
width: 70%;
height: 20%;
overflow: hidden;
}
.smajlík-zelený .úsměv:after,
.smajlík-zelený .úsměv:before {
content: "";
position: absolute;
top: -50%;
left: 0%;
border-radius: 50%;
background: #84b458;
height: 100%;
width: 97%;
}
.smajlík-zelený .úsměv:after {
background: #84b458;
height: 80%;
top: -40%;
left: 0%;
}
.smajlík-žlutý {
background: #eed16a;
border: 5px solid #dbae51;
position: relative;
}
.smajlík-žlutý .levé-oko {
width: 18%;
height: 18%;
background: #dba652;
position: relative;
top: 29%;
left: 22%;
border-radius: 50%;
float: left;
}
.smajlík-žlutý .pravé-oko {
width: 18%;
height: 18%;
border-radius: 50%;
position: relative;
background: #dba652;
top: 29%;
right: 22%;
float: right;
}
.smajlík-žlutý .úsměv {
position: absolute;
top: 67%;
left: 19%;
width: 65%;
height: 14%;
background: #dba652;
overflow: hidden;
border-radius: 8px;
}
.smajlík-červený {
background: #ee9295;
border: 5px solid #e27378;
position: relative;
}
.smajlík-červený .levé-oko {
width: 18%;
height: 18%;
background: #d96065;
position: relative;
top: 29%;
left: 22%;
border-radius: 50%;
float: left;
}
.smajlík-červený .pravé-oko {
width: 18%;
height: 18%;
border-radius: 50%;
position: relative;
background: #d96065;
top: 29%;
right: 22%;
float: right;
}
.smajlík-červený .úsměv {
position: absolute;
top: 57%;
left: 16.5%;
width: 70%;
height: 20%;
overflow: hidden;
}
.smajlík-červený .úsměv:after,
.smajlík-červený .úsměv:before {
content: "";
position: absolute;
top: 50%;
left: 0%;
border-radius: 50%;
background: #d96065;
height: 100%;
width: 97%;
}
.smajlík-červený .úsměv: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="kontejner">
<div class="smajlík-zelený">
<div class="levé-oko"></div>
<div class="pravé-oko"></div>
<div class="úsměv"></div>
</div>
<div class="smajlík-žlutý">
<div class="levé-oko"></div>
<div class="pravé-oko"></div>
<div class="úsměv"></div>
</div>
<div class="smajlík-červený">
<div class="levé-oko"></div>
<div class="pravé-oko"></div>
<div class="úsměv"></div>
</div>
</div>
<textarea id="log">Zde se zobrazí události!
</textarea>
<script src="script.js"></script>
</body>
</html>relatedTarget může být nullVlastnost relatedTarget může být null.
To se běžně stává a znamená to jen to, že ukazatel nepřišel z jiného elementu, ale zvnějšku okna, nebo že okno opustil.
Na tuto možnost bychom měli pamatovat, když používáme událost.relatedTarget v našem kódu. Přistoupíme-li k událost.relatedTarget.tagName, nastane chyba.
Přeskakování elementů
Událost mousemove se spustí, když je ukazatel přesunut. To však neznamená, že tuto událost spustí každý pixel, přes který se ukazatel přesune.
Prohlížeč si jednou za čas zkontroluje pozici myši, a pokud zjistí, že se změnila, vyvolá události.
To znamená, že když návštěvník pohybuje myší příliš rychle, může některé DOM elementy přeskočit:
Jestliže se myš pohybuje velmi rychle z elementu #OD do elementu #DO, jak je zobrazeno výše, může přeskočit mezilehlé elementy <div> (nebo některé z nich). Může se spustit událost mouseout na #OD a hned poté mouseover na #DO.
To zlepšuje výkon, jelikož mezilehlých elementů může být mnoho. Opravdu nechceme zpracovávat vstup na a výstup z každého z nich.
Na druhou stranu bychom měli mít na paměti, že ukazatel myši „nenavštíví“ všechny elementy po cestě a může přes ně „skákat“.
Konkrétně je možné, že ukazatel skočí zvnějšku okna přímo doprostřed stránky. V takovém případě relatedTarget je null, protože přichází „odnikud“:
Můžete si to vyzkoušet „naživo“ na testovacím příkladu níže.
Jeho HTML kód obsahuje dva vnořené elementy: <div id="dítě"> se nachází uvnitř <div id="rodič">. Pokud nad nimi budete rychle pohybovat myší, možná vyvolá události jen dětský div, možná jen rodičovský a možná vůbec žádné události nenastanou.
Zkuste také přesunout ukazatel na dětský div a pak jej přesunout rychle dolů přes rodičovský. Bude-li pohyb dostatečně rychlý, bude rodičovský element ignorován. Ukazatel ho přeskočí bez povšimnutí.
let rodič = document.getElementById('rodič');
rodič.onmouseover = rodič.onmouseout = rodič.onmousemove = handler;
function handler(událost) {
let typ = událost.type;
while (typ.length < 11) typ += ' ';
log(typ + " target=" + událost.target.id)
return false;
}
function vymažText() {
text.value = "";
posledníZpráva = "";
}
let časPosledníZprávy = 0;
let posledníZpráva = "";
let početOpakování = 1;
function log(zpráva) {
if (časPosledníZprávy == 0) časPosledníZprávy = new Date();
let čas = new Date();
if (čas - časPosledníZprávy > 500) {
zpráva = '------------------------------\n' + zpráva;
}
if (zpráva === posledníZpráva) {
početOpakování++;
if (početOpakování == 2) {
text.value = text.value.trim() + ' x 2\n';
} else {
text.value = text.value.slice(0, text.value.lastIndexOf('x') + 1) + početOpakování + "\n";
}
} else {
početOpakování = 1;
text.value += zpráva + "\n";
}
text.scrollTop = text.scrollHeight;
časPosledníZprávy = čas;
posledníZpráva = zpráva;
}#rodič {
background: #99C0C3;
width: 160px;
height: 120px;
position: relative;
}
#dítě {
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="rodič">rodič
<div id="dítě">dítě</div>
</div>
<textarea id="text"></textarea>
<input onclick="vymažText()" value="Vymazat" type="button">
<script src="script.js"></script>
</body>
</html>mouseover, musí být i mouseoutPři rychlém pohybu myší mohou být mezilehlé elementy ignorovány, ale jedno víme jistě: jestliže ukazatel „oficiálně“ vstoupil na element (byla generována událost mouseover), pak při jeho opuštění vždy obdržíme mouseout.
Událost mouseout při opuštění dítěte
Důležitou vlastností události mouseout je, že se spustí, když se ukazatel přemístí z elementu na jeho potomka, např. v následujícím HTML kódu z #rodič na #dítě:
<div id="rodič">
<div id="dítě">...</div>
</div>
Pokud jsme na #rodič a přesuneme ukazatel hlouběji na #dítě, pak dostaneme mouseout na #rodič!
Může to vypadat divně, ale má to jednoduché vysvětlení.
Podle logiky prohlížeče může být ukazatel myši pouze na jediném elementu současně – na tom nejvnořenějším a podle z-indexu vrchním.
Když se tedy přesune na jiný element (třeba i na potomka), opustí předcházející.
Prosíme všimněte si dalšího důležitého detailu zpracování událostí.
Událost mouseover na potomku bublá. Jestliže tedy #rodič má handler mouseover, spustí se:
Na následujícím příkladu to vidíte velmi dobře: <div id="dítě"> je uvnitř <div id="rodič">. Na elementu #rodič jsou handlery mouseover/out, které vypisují detaily událostí.
Když přesunete myš z #rodič na #dítě, uvidíte na #rodič dvě události:
mouseout [target: rodič](opuštění rodiče), pakmouseover [target: dítě](příchod na dítě, probublala).
function mouselog(událost) {
let d = new Date();
text.value += `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()} | ${událost.type} [target: ${událost.target.id}]\n`.replace(/(:|^)(\d\D)/, '$10$2');
text.scrollTop = text.scrollHeight;
}#rodič {
background: #99C0C3;
width: 160px;
height: 120px;
position: relative;
}
#dítě {
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="rodič" onmouseover="mouselog(event)" onmouseout="mouselog(event)">rodič
<div id="dítě">dítě</div>
</div>
<textarea id="text"></textarea>
<input type="button" onclick="text.value=''" value="Clear">
<script src="script.js"></script>
</body>
</html>Jak je vidět, když se ukazatel přemístí z elementu #rodič na element #dítě, spustí se na rodičovském elementu dvě události: mouseout a mouseover:
rodič.onmouseout = function(událost) {
/* událost.target: rodičovský element */
};
rodič.onmouseover = function(událost) {
/* událost.target: dětský element (probublala) */
};
Pokud v handlerech neprozkoumáme událost.target, může to vypadat tak, že ukazatel myši opustil element #rodič a hned pak se na něj vrátil.
To však není tento případ! Ukazatel je neustále na rodiči, jen se přemístil hlouběji na dětský element.
Pokud se při opuštění rodičovského elementu mají provést nějaké akce, např. v rodič.onmouseout se má spustit animace, pak je zpravidla nechceme, když se ukazatel jen přemístí hlouběji dovnitř #rodič.
Abychom se tomu vyhnuli, můžeme v handleru prověřovat relatedTarget, a pokud je myš stále uvnitř elementu, budeme takovou událost ignorovat.
Alternativně můžeme použít jiné události: mouseenter a mouseleave, které nyní probereme. Ty tento problém nemají.
Události mouseenter a mouseleave
Události mouseenter/mouseleave se podobají mouseover/mouseout. Spustí se, když ukazatel myši vstoupí na/opustí element.
Jsou mezi nimi však dva důležité rozdíly:
- Přesuny uvnitř elementu, na potomky a z nich, se nepočítají.
- Události
mouseenter/mouseleavenebublají.
Tyto události jsou extrémně jednoduché.
Když ukazatel vstoupí na element, spustí se mouseenter. Na přesné poloze ukazatele uvnitř elementu nebo jeho potomků nezáleží.
Když ukazatel opustí element, spustí se mouseleave.
Následující příklad se podobá výše uvedenému, ale vrchní element nyní obsahuje mouseenter/mouseleave místo mouseover/mouseout.
Jak vidíte, vygenerují se jedině události, které se vztahují k přesunu ukazatele na vrchní element a z něj. Když se ukazatel přemístí na jeho dítě a zpět, nic se nestane. Přesuny mezi potomky jsou ignorovány.
function mouselog(událost) {
let d = new Date();
text.value += `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()} | ${událost.type} [target: ${událost.target.id}]\n`.replace(/(:|^)(\d\D)/, '$10$2');
text.scrollTop = text.scrollHeight;
}#rodič {
background: #99C0C3;
width: 160px;
height: 120px;
position: relative;
}
#dítě {
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="rodič" onmouseenter="mouselog(event)" onmouseleave="mouselog(event)">rodič
<div id="dítě">dítě</div>
</div>
<textarea id="text"></textarea>
<input type="button" onclick="text.value=''" value="Clear">
<script src="script.js"></script>
</body>
</html>Delegování událostí
Události mouseenter/leave jsou velice jednoduché a snadno se používají, ale nebublají. Nemůžeme tedy na ně použít delegování událostí.
Představme si, že chceme zpracovávat vstup myši na buňky tabulky a jejich opuštění. A těch jsou stovky.
Přirozené řešení by bylo nastavit handler na <table> a zpracovávat události v něm. Jenže mouseenter/leave nebublají. Když se tedy taková událost stane na <td>, dokáže ji zachytit jedině handler na tomto <td>.
Handlery pro mouseenter/leave na <table> se spustí jen tehdy, když ukazatel vstoupí na celou tabulku nebo ji opustí. O přesunech uvnitř ní nemůžeme získat žádné informace.
Použijeme tedy mouseover/mouseout.
Začněme s jednoduchými handlery, které zvýrazňují element pod ukazatelem:
// zvýrazníme element pod ukazatelem
table.onmouseover = function(událost) {
let cíl = událost.target;
cíl.style.background = 'pink';
};
table.onmouseout = function(událost) {
let cíl = událost.target;
cíl.style.background = '';
};
Zde je vidíte v akci. Když se myš přesunuje po elementech této tabulky, aktuální element se zvýrazní:
tabulka.onmouseover = function(událost) {
let cíl = událost.target;
cíl.style.background = 'pink';
text.value += `over -> ${cíl.tagName}\n`;
text.scrollTop = text.scrollHeight;
};
tabulka.onmouseout = function(událost) {
let cíl = událost.target;
cíl.style.background = '';
text.value += `out <- ${cíl.tagName}\n`;
text.scrollTop = text.scrollHeight;
};#text {
display: block;
height: 100px;
width: 456px;
}
#tabulka th {
text-align: center;
font-weight: bold;
}
#tabulka td {
width: 150px;
white-space: nowrap;
text-align: center;
vertical-align: bottom;
padding-top: 5px;
padding-bottom: 12px;
cursor: pointer;
}
#tabulka .nw {
background: #999;
}
#tabulka .n {
background: #03f;
color: #fff;
}
#tabulka .ne {
background: #ff6;
}
#tabulka .w {
background: #ff0;
}
#tabulka .c {
background: #60c;
color: #fff;
}
#tabulka .e {
background: #09f;
color: #fff;
}
#tabulka .sw {
background: #963;
color: #fff;
}
#tabulka .s {
background: #f60;
color: #fff;
}
#tabulka .se {
background: #0c3;
color: #fff;
}
#tabulka .zvýrazni {
background: red;
}<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<table id="tabulka">
<tr>
<th colspan="3">Tabulka <em>Pa-kua</em>: směr, element, barva, význam</th>
</tr>
<tr>
<td class="nw"><strong>Severozápad</strong>
<br>Kov
<br>Stříbrná
<br>Stáří
</td>
<td class="n"><strong>Sever</strong>
<br>Voda
<br>Modrá
<br>Změna
</td>
<td class="ne"><strong>Severovýchod</strong>
<br>Země
<br>Žlutá
<br>Směr
</td>
</tr>
<tr>
<td class="w"><strong>Západ</strong>
<br>Kov
<br>Zlatá
<br>Mládí
</td>
<td class="c"><strong>Střed</strong>
<br>Všechny
<br>Fialová
<br>Harmonie
</td>
<td class="e"><strong>Východ</strong>
<br>Dřevo
<br>Modrá
<br>Budoucnost
</td>
</tr>
<tr>
<td class="sw"><strong>Jihozápad</strong>
<br>Země
<br>Hnědá
<br>Klid
</td>
<td class="s"><strong>Jih</strong>
<br>Oheň
<br>Oranžová
<br>Sláva
</td>
<td class="se"><strong>Jihovýchod</strong>
<br>Dřevo
<br>Zelená
<br>Láska
</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 chtěli zpracovávat přesuny mezi buňkami tabulky <td>: vstup na buňku a její opuštění. Jiné přesuny, například uvnitř jedné buňky nebo mimo buňky, nás nezajímají. Odfiltrujme je.
Můžeme dělat následující:
- Zapamatujeme si aktuálně zvýrazněnou
<td>v proměnné, nazveme jiaktuálníElem. - Při
mouseoverbudeme tuto událost ignorovat, jestliže jsme stále uvnitř aktuální<td>. - Při
mouseoutji budeme ignorovat, jestliže neopustíme aktuální<td>.
Následuje příklad kódu, který počítá se všemi možnými situacemi:
// <td> pod ukazatelem právě teď (pokud nějaká je)
let aktuálníElem = null;
tabulka.onmouseover = function(událost) {
// před vstupem na nový element myš vždy opustí předchozí
// jestliže aktuálníElem je nastaven, neopustili jsme předchozí <td>,
// jde o mouseover uvnitř něj, tuto událost budeme ignorovat
if (aktuálníElem) return;
let cíl = událost.target.closest('td');
// nepřesunuli jsme se na <td> - ignorovat
if (!cíl) return;
// přesunuli jsme se na <td>, ale mimo naši tabulku (to je možné v případě vnořených tabulek)
// ignorovat
if (!tabulka.contains(cíl)) return;
// hurá! vstoupili jsme na novou <td>
aktuálníElem = cíl;
přiPříchodu(aktuálníElem);
};
tabulka.onmouseout = function(událost) {
// pokud jsme nyní mimo jakoukoli <td>, budeme tuto událost ignorovat
// to je pravděpodobně pohyb uvnitř tabulky, ale mimo <td>,
// např. z <tr> na jinou <tr>
if (!aktuálníElem) return;
// opouštíme element - kam? Možná na potomka?
let cílPohybu = událost.relatedTarget;
while (cílPohybu) {
// projdeme řetězec rodičů a prověříme to - pokud jsme stále uvnitř aktuálníElem,
// je to vnitřní přesun - budeme ho ignorovat
if (cílPohybu == aktuálníElem) return;
cílPohybu = cílPohybu.parentNode;
}
// opravdu jsme opustili <td>
přiOdchodu(aktuálníElem);
aktuálníElem = null;
};
// veškeré funkce pro zpracování vstupu/opuštění elementu
function přiPříchodu(elem) {
elem.style.background = 'pink';
// zobrazíme to v textarea
text.value += `dovnitř -> ${aktuálníElem.tagName}.${aktuálníElem.className}\n`;
text.scrollTop = 1e6;
}
function přiOdchodu(elem) {
elem.style.background = '';
// zobrazíme to v textarea
text.value += `ven <- ${elem.tagName}.${elem.className}\n`;
text.scrollTop = 1e6;
}
Opakujeme, že jeho důležité prvky jsou:
- Pro zpracování vstupu na/opuštění jakékoli
<td>v tabulce používá delegování událostí. Je tedy založen namouseover/out, ne namouseenter/leave, která nebublá, a tedy neumožňuje delegování. - Další události, například přesun mezi potomky
<td>, jsou odfiltrovány, takže funkcepřiPříchodu/přiOdchoduse spustí jen tehdy, když ukazatel vstoupí na celou<td>nebo ji opustí.
Zde je celý příklad se všemi detaily:
// <td> pod ukazatelem právě teď (pokud nějaká je)
let aktuálníElem = null;
tabulka.onmouseover = function(událost) {
// před vstupem na nový element myš vždy opustí předchozí
// jestliže aktuálníElem je nastaven, neopustili jsme předchozí <td>,
// jde o mouseover uvnitř něj, tuto událost budeme ignorovat
if (aktuálníElem) return;
let cíl = událost.target.closest('td');
// nepřesunuli jsme se na <td> - ignorovat
if (!cíl) return;
// přesunuli jsme se na <td>, ale mimo naši tabulku (to je možné v případě vnořených tabulek)
// ignorovat
if (!tabulka.contains(cíl)) return;
// hurá! vstoupili jsme na novou <td>
aktuálníElem = cíl;
přiPříchodu(aktuálníElem);
};
tabulka.onmouseout = function(událost) {
// pokud jsme nyní mimo jakoukoli <td>, budeme tuto událost ignorovat
// to je pravděpodobně pohyb uvnitř tabulky, ale mimo <td>,
// např. z <tr> na jinou <tr>
if (!aktuálníElem) return;
// opouštíme element - kam? Možná na potomka?
let cílPohybu = událost.relatedTarget;
while (cílPohybu) {
// projdeme řetězec rodičů a prověříme to - pokud jsme stále uvnitř aktuálníElem,
// je to vnitřní přesun - budeme ho ignorovat
if (cílPohybu == aktuálníElem) return;
cílPohybu = cílPohybu.parentNode;
}
// opravdu jsme opustili <td>
přiOdchodu(aktuálníElem);
aktuálníElem = null;
};
// veškeré funkce pro zpracování vstupu/opuštění elementu
function přiPříchodu(elem) {
elem.style.background = 'pink';
// zobrazíme to v textarea
text.value += `dovnitř -> ${aktuálníElem.tagName}.${aktuálníElem.className}\n`;
text.scrollTop = 1e6;
}
function přiOdchodu(elem) {
elem.style.background = '';
// zobrazíme to v textarea
text.value += `ven <- ${elem.tagName}.${elem.className}\n`;
text.scrollTop = 1e6;
}#text {
display: block;
height: 100px;
width: 456px;
}
#tabulka th {
text-align: center;
font-weight: bold;
}
#tabulka td {
width: 150px;
white-space: nowrap;
text-align: center;
vertical-align: bottom;
padding-top: 5px;
padding-bottom: 12px;
cursor: pointer;
}
#tabulka .nw {
background: #999;
}
#tabulka .n {
background: #03f;
color: #fff;
}
#tabulka .ne {
background: #ff6;
}
#tabulka .w {
background: #ff0;
}
#tabulka .c {
background: #60c;
color: #fff;
}
#tabulka .e {
background: #09f;
color: #fff;
}
#tabulka .sw {
background: #963;
color: #fff;
}
#tabulka .s {
background: #f60;
color: #fff;
}
#tabulka .se {
background: #0c3;
color: #fff;
}
#tabulka .highlight {
background: red;
}<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<table id="tabulka">
<tr>
<th colspan="3">Tabulka <em>Pa-kua</em>: směr, element, barva, význam</th>
</tr>
<tr>
<td class="nw"><strong>Severozápad</strong>
<br>Kov
<br>Stříbrná
<br>Stáří
</td>
<td class="n"><strong>Sever</strong>
<br>Voda
<br>Modrá
<br>Změna
</td>
<td class="ne"><strong>Severovýchod</strong>
<br>Země
<br>Žlutá
<br>Směr
</td>
</tr>
<tr>
<td class="w"><strong>Západ</strong>
<br>Kov
<br>Zlatá
<br>Mládí
</td>
<td class="c"><strong>Střed</strong>
<br>Všechny
<br>Fialová
<br>Harmonie
</td>
<td class="e"><strong>Východ</strong>
<br>Dřevo
<br>Modrá
<br>Budoucnost
</td>
</tr>
<tr>
<td class="sw"><strong>Jihozápad</strong>
<br>Země
<br>Hnědá
<br>Klid
</td>
<td class="s"><strong>Jih</strong>
<br>Oheň
<br>Oranžová
<br>Sláva
</td>
<td class="se"><strong>Jihovýchod</strong>
<br>Dřevo
<br>Zelená
<br>Láska
</td>
</tr>
</table>
<textarea id="text"></textarea>
<input type="button" onclick="text.value=''" value="Clear">
<script src="script.js"></script>
</body>
</html>Zkuste si přesunovat ukazatel dovnitř a ven z buněk tabulky a uvnitř nich. Rychle nebo pomalu, na tom nezáleží. Zvýrazní se jen <td> jako celek, na rozdíl od výše uvedeného příkladu.
Shrnutí
Probrali jsme události mouseover, mouseout, mousemove, mouseenter a mouseleave.
Je dobré si zapamatovat následující:
- Při rychlém pohybu myší mohou být přeskočeny mezilehlé elementy.
- Události
mouseover/outamouseenter/leavemají další vlastnost:relatedTarget. To je element, ze kterého přicházíme / na který odcházíme, doplněk ktarget.
Události mouseover/out se spustí i tehdy, když se přesuneme z rodičovského elementu na dětský. Prohlížeč předpokládá, že ukazatel může být pouze na jednom elementu současně – na tom nejhlubším.
Události mouseenter/leave se v tomto ohledu liší: spustí se jen tehdy, když myš vstoupí na celý element nebo jej opustí. Kromě toho nebublají.
Komentáře
<code>, pro několik řádků je obalte značkou<pre>, pro více než 10 řádků vložte odkaz na pískoviště (plnkr, jsbin, codepen…)