Sichqoncha elementlar orasida harakatlanayotganda sodir bo’ladigan hodisalar haqida batafsil to’xtalib o’taylik.
Hodisalar mouseover/mouseout, relatedTarget
mouseover
hodisasi sichqoncha ko’rsatkichi element ustiga kelganda sodir bo’ladi, mouseout
esa uni tark etganda.
Bu hodisalar maxsus, chunki ularda relatedTarget
xossasi mavjud. Bu xossa target
ni to’ldiradi. Sichqoncha bitta elementdan ikkinchisiga o’tganda, ulardan biri target
bo’ladi, ikkinchisi esa – relatedTarget
.
mouseover
uchun:
event.target
– sichqoncha ustiga kelgan element.event.relatedTarget
– sichqoncha kelgan element (relatedTarget
→target
).
mouseout
uchun aksincha:
event.target
– sichqoncha tark etgan element.event.relatedTarget
– ko’rsatkich ostidagi yangi element, sichqoncha o’tgan joy (target
→relatedTarget
).
Quyidagi misolda har bir yuz va uning xususiyatlari alohida elementlardir. Sichqonchani harakatlantirsangiz, matn maydonida sichqoncha hodisalarini ko’rishingiz mumkin.
Har bir hodisa target
va relatedTarget
haqida ma’lumotga ega:
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">
Voqealar shu yerda chiqadi!
</textarea>
<script src="script.js"></script>
</body>
</html>
relatedTarget
null
bo’lishi mumkinrelatedTarget
xossasi null
bo’lishi mumkin.
Bu normal va shunchaki sichqoncha boshqa elementdan emas, balki oynadan tashqaridan kelganini anglatadi. Yoki u oynani tark etganini.
Kodimizda event.relatedTarget
dan foydalanganda bu imkoniyatni yodda tutishimiz kerak. Agar biz event.relatedTarget.tagName
ga murojaat qilsak, xato yuz beradi.
Elementlarni o’tkazib yuborish
mousemove
hodisasi sichqoncha harakatlanayotganda ishga tushadi. Lekin bu har bir piksel hodisaga olib kelishini anglatmaydi.
Brauzer vaqti-vaqti bilan sichqoncha pozitsiyasini tekshiradi. Va agar o’zgarishlarni sezsa, hodisalarni ishga tushiradi.
Bu shuni anglatadiki, agar tashrif buyuruvchi sichqonchani juda tez harakatlantirsa, ba’zi DOM-elementlar o’tkazib yuborilishi mumkin:
Agar sichqoncha yuqorida chizilgandek #FROM
dan #TO
elementlariga juda tez harakat qilsa, oraliq <div>
elementlari (yoki ularning ba’zilari) o’tkazib yuborilishi mumkin. mouseout
hodisasi #FROM
da ishga tushishi va keyin darhol #TO
da mouseover
bo’lishi mumkin.
Bu unumdorlik uchun yaxshi, chunki ko’plab oraliq elementlar bo’lishi mumkin. Biz har biriga kirish va chiqishni qayta ishlamoqchi emasmiz.
Boshqa tomondan, sichqoncha ko’rsatkichi yo’l bo’ylab barcha elementlarni “tashrif buyurmasligini” yodda tutishimiz kerak. U “sakrashi” mumkin.
Xususan, ko’rsatkich oynadan tashqaridan sahifaning o’rtasiga to’g’ri sakrashi mumkin. Bunday holda relatedTarget
null
bo’ladi, chunki u “hech qayerdan” kelgan:
Buni quyidagi test stendida “jonli” tekshirishingiz mumkin.
Uning HTML ikkita ichki elementga ega: <div id="child">
<div id="parent">
ichida. Agar sichqonchani ular ustida tez harakatlantisangiz, ehtimol faqat bola div hodisalarni ishga tushiradi, yoki ehtimol ota-onasi, yoki ehtimol umuman hodisalar bo’lmaydi.
Shuningdek, ko’rsatkichni bola div
ga olib boring, so’ngra ota-onasi orqali tezda pastga chiqaring. Agar harakat etarlicha tez bo’lsa, ota-ona elementi e’tiborga olinmaydi. Sichqoncha ota-ona elementini sezmasdan kesib o’tadi.
let parent = document.getElementById("parent");
parent.onmouseover = parent.onmouseout = parent.onmousemove = handler;
function handler(event) {
let type = event.type;
while (type < 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">
ota
<div id="child">bola</div>
</div>
<textarea id="text"></textarea>
<input onclick="clearText()" value="Clear" type="button" />
<script src="script.js"></script>
</body>
</html>
mouseover
ishga tushsa, mouseout
bo’lishi kerakTez sichqoncha harakatlarida oraliq elementlar e’tiborga olinmasligi mumkin, lekin bir narsani aniq bilamiz: agar ko’rsatkich elementga “rasmiy” ravishda kirsa (mouseover
hodisasi hosil bo’lsa), uni tark etganda har doim mouseout
ni olamiz.
Bola uchun ketayotganda mouseout
mouseout
ning muhim xususiyati – u ko’rsatkich elementdan uning avlodiga o’tganda, masalan bu HTML da #parent
dan #child
ga o’tganda ishga tushadi:
<div id="parent">
<div id="child">...</div>
</div>
Agar biz #parent
da bo’lsak va keyin ko’rsatkichni #child
ga chuqurroq olib borsak, #parent
da mouseout
ni olamiz!
Bu g’alati tuyulishi mumkin, lekin osonlikcha tushuntiriladi.
Brauzer mantiqiga ko’ra, sichqoncha kursori istalgan vaqtda faqat bitta element ustida bo’lishi mumkin – eng ichki va z-index bo’yicha eng yuqori.
Shuning uchun agar u boshqa elementga (hatto avlodga) o’tsa, oldingi birini tark etadi.
Hodisalarni qayta ishlashning yana bir muhim tafsilotiga e’tibor bering.
Avloddagi mouseover
hodisasi yuqoriga bubble qiladi. Shuning uchun agar #parent
da mouseover
ishlov beruvchi bo’lsa, u ishga tushadi:
Buni quyidagi misolda juda yaxshi ko’rishingiz mumkin: <div id="child">
<div id="parent">
ichida. #parent
elementida hodisa tafsilotlarini chiqaruvchi mouseover/out
ishlov beruvchilari bor.
Agar sichqonchani #parent
dan #child
ga olib borsangiz, #parent
da ikkita hodisani ko’rasiz:
mouseout [target: parent]
(ota-onani tark etdi), keyinmouseover [target: child]
(bolaga keldi, bubble qildi).
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>
Ko’rsatilgandek, ko’rsatkich #parent
elementidan #child
ga o’tganda, ota-ona elementida ikkita ishlov beruvchi ishga tushadi: mouseout
va mouseover
:
parent.onmouseout = function(event) {
/* event.target: parent element */
};
parent.onmouseover = function(event) {
/* event.target: child element (bubbled) */
};
Agar biz ishlov beruvchilar ichida event.target
ni tekshirmasak, sichqoncha ko’rsatkichi #parent
elementini tark etgandek va keyin darhol uning ustiga qaytgandek tuyulishi mumkin.
Lekin bunday emas! Ko’rsatkich hali ham ota-ona ustida, u shunchaki bola elementiga chuqurroq o’tgan.
Agar ota-ona elementni tark etganda ba’zi harakatlar bo’lsa, masalan parent.onmouseout
da animatsiya ishlasa, biz odatda ko’rsatkich shunchaki #parent
ga chuqurroq kirganda buni xohlamaymiz.
Buni oldini olish uchun ishlov beruvchida relatedTarget
ni tekshirishimiz va agar sichqoncha hali ham element ichida bo’lsa, bunday hodisani e’tiborsiz qoldirishimiz mumkin.
Shu kabi muammolarga ega bo’lmagan boshqa hodisalardan foydalanishimiz mumkin: mouseenter
va mouseleave
, bularni endi ko’rib chiqamiz.
Hodisalar mouseenter va mouseleave
mouseenter/mouseleave
hodisalari mouseover/mouseout
ga o’xshash. Ular sichqoncha ko’rsatkichi elementga kirganda/chiqayotganda ishga tushadi.
Lekin ikkita muhim farq bor:
- Element ichidagi, avlodlarga/dan o’tishlar hisobga olinmaydi.
mouseenter/mouseleave
hodisalari bubble qilmaydi.
Bu hodisalar juda oddiy.
Ko’rsatkich elementga kirganda – mouseenter
ishga tushadi. Ko’rsatkichning element yoki uning avlodlari ichidagi aniq joylashuvi muhim emas.
Ko’rsatkich elementni tark etganda – mouseleave
ishga tushadi.
Bu misol yuqoridagiga o’xshash, lekin endi yuqori elementda mouseover/mouseout
o’rniga mouseenter/mouseleave
bor.
Ko’rib turganimizdek, hosil bo’lgan yagona hodisalar ko’rsatkichni yuqori elementga kirish va chiqish bilan bog’liq. Ko’rsatkich bolaga o’tganda va orqaga qaytganda hech narsa bo’lmaydi. Avlodlar orasidagi o’tishlar e’tiborga olinmaydi
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)"
>
ota
<div id="child">bola</div>
</div>
<textarea id="text"></textarea>
<input type="button" onclick="text.value=''" value="Clear" />
<script src="script.js"></script>
</body>
</html>
Hodisa delegatsiyasi
mouseenter/leave
hodisalari juda oddiy va ishlatish oson. Lekin ular bubble qilmaydi. Shuning uchun biz ular bilan hodisa delegatsiyasidan foydalana olmaymiz.
Tasavvur qiling, biz jadval katakchalarida sichqoncha kirish/chiqishini qayta ishlamoqchimiz. Va yuzlab katak bor.
Tabiiy yechim – <table>
ga ishlov beruvchi o’rnatish va hodisalarni u yerda qayta ishlash bo’ladi. Lekin mouseenter/leave
bubble qilmaydi. Shuning uchun agar bunday hodisa <td>
da sodir bo’lsa, faqat o’sha <td>
dagi ishlov beruvchi uni ushlashi mumkin.
<table>
dagi mouseenter/leave
uchun ishlov beruvchilar faqat ko’rsatkich butun jadvalga kirganda/chiqayotganda ishga tushadi. Uning ichidagi o’tishlar haqida hech qanday ma’lumot olish mumkin emas.
Shuning uchun mouseover/mouseout
dan foydalanamiz.
Sichqoncha ostidagi elementni ajratib ko’rsatuvchi oddiy ishlov beruvchilar bilan boshlaylik:
// sichqoncha ostidagi elementni ajratib ko'rsataylik
table.onmouseover = function(event) {
let target = event.target;
target.style.background = 'pink';
};
table.onmouseout = function(event) {
let target = event.target;
target.style.background = '';
};
Mana ular amalda. Sichqoncha ushbu jadvalning elementlari bo’ylab harakatlanayotganda, joriy biri ajratiladi:
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> jadvali: Yo'nalish, Element, Rang, Ma'no
</th>
</tr>
<tr>
<td class="nw">
<strong>Shimoli-g'arbiy</strong> <br />Metal <br />Kumush
<br />Oqsoqollar
</td>
<td class="n">
<strong>Shimoliy</strong> <br />Suv <br />Ko'k <br />O'zgarish
</td>
<td class="ne">
<strong>Shimoli-sharqiy</strong> <br />Yer <br />Sariq <br />Yo'nalish
</td>
</tr>
<tr>
<td class="w">
<strong>G'arbiy</strong> <br />Metal <br />Oltin <br />Yoshlik
</td>
<td class="c">
<strong>Markaz</strong> <br />Hammasi <br />Binafsha <br />Uyg'unlik
</td>
<td class="e">
<strong>Sharqiy</strong> <br />Yog'och <br />Ko'k <br />Kelajak
</td>
</tr>
<tr>
<td class="sw">
<strong>Janubi-g'arbiy</strong> <br />Yer <br />Jigarrang
<br />Xotirjamlik
</td>
<td class="s">
<strong>Janubiy</strong> <br />Olov <br />To'q sariq
<br />Shon-shuhrat
</td>
<td class="se">
<strong>Janubi-sharqiy</strong> <br />Yog'och <br />Yashil <br />Sevgi
</td>
</tr>
</table>
<textarea id="text"></textarea>
<input type="button" onclick="text.value=''" value="Clear" />
<script src="script.js"></script>
</body>
</html>
Bizning holatda biz jadval katakchalarida <td>
o’tishlarni qayta ishlamoqchimiz: katakka kirish va uni tark etish. Boshqa o’tishlar, masalan katak ichida yoki hech qanday katakdan tashqarida, bizni qiziqtirmaydi. Keling, ularni filtrlaylik.
Mana nima qilishimiz mumkin:
- Hozirgi ajratilgan
<td>
ni o’zgaruvchida eslab qolish, unicurrentElem
deb ataymiz. mouseover
da – agar biz hali ham joriy<td>
ichida bo’lsak, hodisani e’tiborsiz qoldirish.mouseout
da – agar joriy<td>
ni tark etmagan bo’lsak, e’tiborsiz qoldirish.
Mana barcha mumkin bo’lgan holatlarni hisobga olgan kod misoli:
// Hozir ajratilgan element
let currentElem = null;
table.onmouseover = function(event) {
// mouseover ishga tushganda va biz allaqachon biror elementni ajratgan bo'lsak,
// unda avvalgi ajratishni bekor qilishdan oldin yangi hodisani e'tiborsiz qoldiramiz
if (currentElem) return;
let target = event.target.closest('td');
// Biz td ga o'tmadik - e'tiborsiz qoldirish
if (!target) return;
// Biz ichki jadvalga o'tdik (mumkin), uni e'tiborsiz qoldirish
if (!table.contains(target)) return;
// Hurray! Biz yangi td ga kirdik
currentElem = target;
onEnter(currentElem);
};
table.onmouseout = function(event) {
// Agar biz hozirda hech qanday elementda bo'lmasak, e'tiborsiz qoldirish
if (!currentElem) return;
// Biz elementni tark etayotgiz - qayerga? Ehtimol avlodga?
let relatedTarget = event.relatedTarget;
while (relatedTarget) {
// Yo'q! Biz currentElem ning ichiga o'tdik - bu ichki o'tish, e'tiborsiz qoldirish
if (relatedTarget == currentElem) return;
relatedTarget = relatedTarget.parentNode;
}
// Biz haqiqatdan ham elementni tark etdik
onLeave(currentElem);
currentElem = null;
};
// har qanday elementga kirish/chiqish funksiyalari
function onEnter(elem) {
elem.style.background = 'pink';
// textarea da buni ko'rsatish
text.value += `over -> ${currentElem.tagName}.${currentElem.className}\n`;
text.scrollTop = text.scrollHeight;
}
function onLeave(elem) {
elem.style.background = '';
// textarea da buni ko'rsatish
text.value += `leave <- ${elem.tagName}.${elem.className}\n`;
text.scrollTop = text.scrollHeight;
}
Yana bir bor, muhim xususiyatlar:
- U jadval ichidagi har qanday
<td>
ga kirish/chiqishni qayta ishlash uchun hodisa delegatsiyasidan foydalanadi. Shuning uchun u bubble qilmaydigan va shuning uchun delegatsiyaga ruxsat bermaydiganmouseenter/leave
o’rnigamouseover/out
ga tayangan. <td>
avlodlari orasida harakatlanish kabi qo’shimcha hodisalar filtrlangan, shuning uchunonEnter/Leave
faqat ko’rsatkich<td>
ni butunlay tark etganda yoki kirganda ishlaydi.
Mana barcha tafsilotlar bilan to’liq misol:
// <td> hozir sichqoncha ostida (agar mavjud bo'lsa)
let currentElem = null;
table.onmouseover = function (event) {
// yangi elementni kiritishdan oldin sichqoncha har doim oldingi elementni tark etadi
// agar currentElem o'rnatilgan bo'lsa, biz oldingi <td> dan chiqmadik,
// bu uning ichida sichqonchani bosish, hodisani e'tiborsiz qoldiring
if (currentElem) return;
let target = event.target.closest("td");
// biz <td> ga ko'chdik - e'tibor bermang
if (!target) return;
// <td> ga ko'chirildi, lekin jadvalimizdan tashqarida (jadvallar o'rnatilgan bo'lsa mumkin)
// e'tibor bermang
if (!table.contains(target)) return;
// urrraaa! biz yangi <td> ga kirdik
currentElem = target;
onEnter(currentElem);
};
table.onmouseout = function (event) {
// agar biz hozir biron bir <td> dan tashqarida bo'lsak, hodisaga e'tibor bermang
// bu jadval ichidagi harakat, lekin <td> dan tashqarida,
// masalan. <tr> dan boshqa <tr> ga
if (!currentElem) return;
// biz elementni qoldiramiz – qayerga? Balki vorisigadir?
let relatedTarget = event.relatedTarget;
while (relatedTarget) {
// ota-ona zanjiriga o'ting va biz hali ham currentElem ichida ekanligimizni tekshiring
// keyin bu ichki o'tish - unga e'tibor bermang
if (relatedTarget == currentElem) return;
relatedTarget = relatedTarget.parentNode;
}
// biz <td> ni tark etdik.
onLeave(currentElem);
currentElem = null;
};
// elementni kiritish/chiqish bilan bog'liq har qanday funktsiyalar
function onEnter(elem) {
elem.style.background = "pink";
// buni matn maydonida ko'rsating
text.value += `over -> ${currentElem.tagName}.${currentElem.className}\n`;
text.scrollTop = 1e6;
}
function onLeave(elem) {
elem.style.background = "";
// buni matn maydonida ko'rsating
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> jadvali: Yo'nalish, Element, Rang, Ma'no
</th>
</tr>
<tr>
<td class="nw">
<strong>Shimoli-g'arbiy</strong> <br />Metal <br />Kumush
<br />Oqsoqollar
</td>
<td class="n">
<strong>Shimoliy</strong> <br />Suv <br />Ko'k <br />O'zgarish
</td>
<td class="ne">
<strong>Shimoli-sharqiy</strong> <br />Yer <br />Sariq <br />Yo'nalish
</td>
</tr>
<tr>
<td class="w">
<strong>G'arbiy</strong> <br />Metal <br />Oltin <br />Yoshlik
</td>
<td class="c">
<strong>Markaz</strong> <br />Hammasi <br />Binafsha <br />Uyg'unlik
</td>
<td class="e">
<strong>Sharqiy</strong> <br />Yog'och <br />Ko'k <br />Kelajak
</td>
</tr>
<tr>
<td class="sw">
<strong>Janubi-g'arbiy</strong> <br />Yer <br />Jigarrang
<br />Xotirjamlik
</td>
<td class="s">
<strong>Janubiy</strong> <br />Olov <br />To'q sariq
<br />Shon-shuhrat
</td>
<td class="se">
<strong>Janubi-sharqiy</strong> <br />Yog'och <br />Yashil <br />Sevgi
</td>
</tr>
</table>
<textarea id="text"></textarea>
<input type="button" onclick="text.value=''" value="Clear" />
<script src="script.js"></script>
</body>
</html>
Kursorni jadval katakchalariga va ichiga kirish va chiqishda harakatlantiring. Tez yoki sekin – farqi yo’q. Oldingi misoldan farqli o’laroq, faqat <td>
butunlay ajratiladi.
Xulosa
Biz mouseover
, mouseout
, mousemove
, mouseenter
va mouseleave
hodisalarini ko’rib chiqdik.
Quyidagi narsalarni qayd etish yaxshi:
- Tez sichqoncha harakati oraliq elementlarni o’tkazib yuborishi mumkin.
mouseover/out
vamouseenter/leave
hodisalari qo’shimcha xossaga ega:relatedTarget
. Bu biz kelayotgan/borayotgan element,target
ga qo’shimcha.
mouseover/out
hodisalari ota-ona elementdan bola elementga o’tganimizda ham ishga tushadi. Brauzer sichqoncha bir vaqtda faqat bitta element ustida bo’lishi mumkin deb hisoblaydi – eng chuqur biri.
mouseenter/leave
hodisalari bu jihatdan boshqacha: ular faqat sichqoncha elementga butunlay kirganda va chiqayotganda ishga tushadi. Shuningdek, ular bubble qilmaydi.
Izohlar
<code>
yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>
yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)