Hodisa – bu biror narsa sodir bo’lganining signali. Barcha DOM tugunlar bunday signallar hosil qiladi (lekin hodisalar faqat DOM bilan cheklanmaydi).
Eng foydali DOM hodisalarning ro’yxati, shunchaki ko’rib chiqish uchun:
Sichqoncha hodisalari:
click
– sichqoncha element ustiga bosganda (sensorli ekran qurilmalari buni teginishda hosil qiladi).contextmenu
– sichqoncha element ustiga o’ng tugma bilan bosganda.mouseover
/mouseout
– sichqoncha kursori element ustiga kelganda / chiqib ketganda.mousedown
/mouseup
– sichqoncha tugmasi element ustida bosilganda / qo’yib yuborilganda.mousemove
– sichqoncha harakatlantirilganda.
Klaviatura hodisalari:
keydown
vakeyup
– klaviatura tugmasi bosilganda va qo’yib yuborilganda.
Forma elementlari hodisalari:
submit
– tashrif buyuruvchi<form>
ni yuborganda.focus
– tashrif buyuruvchi elementga, masalan<input>
ga fokuslashtirganida.
Hujjat hodisalari:
DOMContentLoaded
– HTML yuklanganda va qayta ishlanganda, DOM to’liq qurilganda.
CSS hodisalari:
transitionend
– CSS-animatsiya tugaganda.
Boshqa ko’plab hodisalar ham mavjud. Keyingi boblarda ma’lum hodisalarning tafsilotlariga to’xtalamiz.
Hodisa ishlov beruvchilari
Hodisalarga javob berish uchun biz ishlov beruvchi tayinlashimiz mumkin – hodisa holatida ishlaydigan funksiya.
Ishlov beruvchilar foydalanuvchi harakatlari holatida JavaScript kodini ishga tushirish usuli.
Ishlov beruvchi tayinlashning bir necha usuli mavjud. Keling, ularni ko’rib chiqaylik, eng oddiydan boshlab.
HTML-atribut
Ishlov beruvchi HTML da on<event>
nomli atribut bilan o’rnatilishi mumkin.
Masalan, input
uchun click
ishlov beruvchisini tayinlash uchun biz onclick
dan foydalanishimiz mumkin:
<input value="Menga bosing" onclick="alert('Bosish!')" type="button">
Sichqoncha bosilganda, onclick
ichidagi kod ishlaydi.
Diqqat qiling, onclick
ichida biz bitta qo’shtirnoqlardan foydalanamiz, chunki atributning o’zi qo’sh qo’shtirnoqlarda. Agar biz kod atribut ichida ekanligini unutib, ichida qo’sh qo’shtirnoqlardan foydalansak, masalan: onclick="alert("Bosish!")"
, u to’g’ri ishlamaydi.
HTML-atribut ko’p kod yozish uchun qulay joy emas, shuning uchun JavaScript funksiyasi yaratib, uni chaqirish yaxshiroq.
Bu yerda bosish countRabbits()
funksiyasini ishga tushiradi:
<script>
function countRabbits() {
for(let i=1; i<=3; i++) {
alert("Quyon raqami " + i);
}
}
</script>
<input type="button" onclick="countRabbits()" value="Quyonlarni sana!">
Ma’lumki, HTML atribut nomlari katta-kichik harfga sezgir emas, shuning uchun ONCLICK
ham onClick
va onCLICK
kabi ishlaydi… Lekin odatda atributlar kichik harflarda yoziladi: onclick
.
DOM xossasi
Biz on<event>
DOM xossasidan foydalanib ishlov beruvchi tayinlashimiz mumkin.
Masalan, elem.onclick
:
<input id="elem" type="button" value="Menga bosing">
<script>
elem.onclick = function() {
alert('Rahmat');
};
</script>
Agar ishlov beruvchi HTML-atribut yordamida tayinlangan bo’lsa, brauzer uni o’qiydi, atribut mazmunidan yangi funksiya yaratadi va uni DOM xossasiga yozadi.
Demak, bu usul aslida avvalgisi bilan bir xil.
Bu ikki kod qismi bir xil ishlaydi:
-
Faqat HTML:
<input type="button" onclick="alert('Bosish!')" value="Tugma">
-
HTML + JS:
<input type="button" id="button" value="Tugma"> <script> button.onclick = function() { alert('Bosish!'); }; </script>
Birinchi misolda HTML atributi button.onclick
ni ishga tushirish uchun ishlatiladi, ikkinchi misolda esa – skript, farq faqat shu.
Faqat bitta onclick
xossasi borligi sababli, biz birdanortiq hodisa ishlov beruvchisini tayinlay olmaymiz.
Quyidagi misolda JavaScript bilan ishlov beruvchi qo’shish mavjud ishlov beruvchini ustiga yozadi:
<input type="button" id="elem" onclick="alert('Oldin')" value="Menga bosing">
<script>
elem.onclick = function() { // mavjud ishlov beruvchini ustiga yozadi
alert('Keyin'); // faqat bu ko'rsatiladi
};
</script>
Ishlov beruvchini olib tashlash uchun – elem.onclick = null
tayinlang.
Elementga kirish: this
Ishlov beruvchi ichidagi this
qiymati elementdir. Ishlov beruvchi o’rnatilgan element.
Quyidagi kodda button
o’z mazmunini this.innerHTML
yordamida ko’rsatadi:
<button onclick="alert(this.innerHTML)">Menga bosing</button>
Mumkin bo’lgan xatolar
Agar siz hodisalar bilan ishlashni boshlayotgan bo’lsangiz – ba’zi nozikliklarni yodda tuting.
Biz mavjud funksiyani ishlov beruvchi sifatida o’rnatishimiz mumkin:
function sayThanks() {
alert('Rahmat!');
}
elem.onclick = sayThanks;
Lekin ehtiyot bo’ling: funksiya sayThanks
sifatida tayinlanishi kerak, sayThanks()
emas.
// to'g'ri
button.onclick = sayThanks;
// noto'g'ri
button.onclick = sayThanks();
Agar qavs qo’shsak, sayThanks()
funksiya chaqiruvi bo’ladi. Demak, oxirgi qator aslida funksiya bajarilishining natijasini, ya’ni undefined
ni (funksiya hech narsa qaytarmaydi) oladi va uni onclick
ga tayinlaydi. Bu ishlamaydi.
…Boshqa tomondan, markupda bizga qavslar kerak:
<input type="button" id="button" onclick="sayThanks()">
Farqni tushuntirish oson. Brauzer atributni o’qiganda, u atribut mazmunidan tanali ishlov beruvchi funksiyasini yaratadi.
Demak, markup ushbu xossani hosil qiladi:
button.onclick = function() {
sayThanks(); // <-- atribut mazmuni bu yerga kiradi
};
Ishlov beruvchilar uchun setAttribute
dan foydalanmang.
Bunday chaqiruv ishlamaydi:
// <body> ga bosish xatolarga olib keladi,
// chunki atributlar doim satrlar, funksiya satrga aylanadi
document.body.setAttribute('onclick', function() { alert(1) });
DOM-xossasi katta-kichik harf muhim.
Ishlov beruvchini elem.onclick
ga tayinlang, elem.ONCLICK
ga emas, chunki DOM xossalari katta-kichik harfga sezgir.
addEventListener
Yuqorida aytilgan ishlov beruvchilarni tayinlash usullarining asosiy muammosi – biz bitta hodisaga bir nechta ishlov beruvchi tayinlay olmaymiz.
Aytaylik, bizning kodimizning bir qismi bosishda tugmani ajratib ko’rsatmoqchi, boshqasi esa bir xil bosishda xabar ko’rsatmoqchi.
Buning uchun ikkita hodisa ishlov beruvchisini tayinlamoqchimiz. Lekin yangi DOM xossasi mavjud birini ustiga yozadi:
input.onclick = function() { alert(1); }
// ...
input.onclick = function() { alert(2); } // avvalgi ishlov beruvchini almashtiradi
Veb standartlari ishlab chiquvchilari buni uzoq vaqt oldin tushunib, addEventListener
va removeEventListener
maxsus metodlari yordamida ishlov beruvchilarni boshqarishning muqobil usulini taklif qildilar. Ular bunday muammodan xoli.
Ishlov beruvchi qo’shish sintaksisi:
element.addEventListener(event, handler, [options]);
event
- Hodisa nomi, masalan
"click"
. handler
- Ishlov beruvchi funksiya.
options
- Xossalari bilan qo’shimcha ixtiyoriy obyekt:
once
: agartrue
bo’lsa, tinglovchi ishga tushgandan keyin avtomatik ravishda olib tashlanadi.capture
: hodisani qaysi fazada qayta ishlash kerakligi, keyinroq Bubbling va Capturing bobida ko’rib chiqiladi. Tarixiy sabablarga ko’ra,options
false/true
ham bo’lishi mumkin, bu{capture: false/true}
bilan bir xil.passive
: agartrue
bo’lsa, ishlov beruvchipreventDefault()
ni chaqirmaydi, buni keyinroq Brauzerni standart harakatlari da tushuntiramiz.
Ishlov beruvchini olib tashlash uchun removeEventListener
dan foydalaning:
element.removeEventListener(event, handler, [options]);
Ishlov beruvchini olib tashlash uchun tayinlangan funksiya bilan aynan bir xil funksiyani uzatishimiz kerak.
Bu ishlamaydi:
elem.addEventListener( "click" , () => alert('Rahmat!'));
// ....
elem.removeEventListener( "click", () => alert('Rahmat!'));
Ishlov beruvchi olib tashlanmaydi, chunki removeEventListener
boshqa funksiyani oladi – bir xil kod bilan, lekin bu muhim emas, chunki bu boshqa funksiya obyekti.
To’g’ri usul:
function handler() {
alert( 'Rahmat!' );
}
input.addEventListener("click", handler);
// ....
input.removeEventListener("click", handler);
Diqqat qiling – agar biz funksiyani o’zgaruvchida saqlamasak, uni olib tashlay olmaymiz. addEventListener
tomonidan tayinlangan ishlov beruvchilarni “qayta o’qish” imkoni yo’q.
addEventListener
ga bir nechta chaqiruv bir nechta ishlov beruvchi qo’shishga imkon beradi:
<input id="elem" type="button" value="Menga bosing"/>
<script>
function handler1() {
alert('Rahmat!');
};
function handler2() {
alert('Yana rahmat!');
}
elem.onclick = () => alert("Salom");
elem.addEventListener("click", handler1); // Rahmat!
elem.addEventListener("click", handler2); // Yana rahmat!
</script>
Yuqoridagi misolda ko’rib turganimizdek, biz ishlov beruvchilarni ham DOM-xossasi, ham addEventListener
yordamida o’rnatishimiz mumkin. Lekin odatda biz faqat bitta usuldan foydalanamiz.
addEventListener
bilan ishlaydiDOM-xossasi orqali tayinlab bo’lmaydigan hodisalar mavjud. Faqat addEventListener
bilan.
Masalan, hujjat yuklanganda va DOM qurilganda ishga tushadigan DOMContentLoaded
hodisasi.
// hech qachon ishlamaydi
document.onDOMContentLoaded = function() {
alert("DOM qurildi");
};
// shu usul bilan ishlaydi
document.addEventListener("DOMContentLoaded", function() {
alert("DOM qurildi");
});
Demak addEventListener
universalroq. Garchi, bunday hodisalar istisno, qoida emas.
Hodisa obyekti
Hodisani to’g’ri qayta ishlash uchun nima sodir bo’lganligi haqida ko’proq bilmoqchimiz. Faqat “bosish” yoki “tugma bosish” emas, balki ko’rsatkich koordinatalari qanday? Qaysi tugma bosilgan? Va hokazo.
Hodisa sodir bo’lganda, brauzer hodisa obyekti yaratadi, unga tafsilotlarni joylashtiradi va uni ishlov beruvchiga argument sifatida uzatadi.
Hodisa obyektidan ko’rsatkich koordinatalarini olish misoli:
<input type="button" value="Menga bosing" id="elem">
<script>
elem.onclick = function(event) {
// hodisa turi, elementi va bosish koordinatalarini ko'rsatish
alert(event.type + " da " + event.currentTarget);
alert("Koordinatalar: " + event.clientX + ":" + event.clientY);
};
</script>
event
obyektining ba’zi xossalari:
event.type
- Hodisa turi, bu yerda
"click"
. event.currentTarget
- Hodisani qayta ishlovchi element. Bu
this
bilan aynan bir xil, agar ishlov beruvchi o’q funksiya bo’lmasa yoki uningthis
boshqa narsaga bog’lanmagan bo’lsa, u holda biz elementnievent.currentTarget
dan olishimiz mumkin. event.clientX / event.clientY
- Ko’rsatkich hodisalari uchun kursorning oynaga nisbatan koordinatalari.
Ko’proq xossalar mavjud. Ularning ko’pchiligi hodisa turiga bog’liq: klaviatura hodisalarida bir xossalar to’plami, ko’rsatkich hodisalarida – boshqasi, biz ularni keyinroq turli hodisalarni batafsil ko’rib chiqishda o’rganamiz.
Agar biz HTML da ishlov beruvchi tayinlasak, event
obyektini ham ishlatishimiz mumkin:
<input type="button" onclick="alert(event.type)" value="Hodisa turi">
Bu mumkin, chunki brauzer atributni o’qiganda, u shunday ishlov beruvchi yaratadi: function(event) { alert(event.type) }
. Ya’ni: uning birinchi argumenti "event"
deb ataladi va tanasi atributdan olinadi.
Obyekt ishlov beruvchilari: handleEvent
Biz addEventListener
yordamida hodisa ishlov beruvchi sifatida faqat funksiya emas, balki obyektni ham tayinlashimiz mumkin. Hodisa sodir bo’lganda, uning handleEvent
metodi chaqiriladi.
Masalan:
<button id="elem">Menga bosing</button>
<script>
let obj = {
handleEvent(event) {
alert(event.type + " da " + event.currentTarget);
}
};
elem.addEventListener('click', obj);
</script>
Ko’rib turganimizdek, addEventListener
ishlov beruvchi sifatida obyektni qabul qilganda, u hodisa holatida obj.handleEvent(event)
ni chaqiradi.
Buning uchun sinfdan ham foydalanishimiz mumkin:
<button id="elem">Menga bosing</button>
<script>
class Menu {
handleEvent(event) {
switch(event.type) {
case 'mousedown':
elem.innerHTML = "Sichqoncha tugmasi bosildi";
break;
case 'mouseup':
elem.innerHTML += "...va qo'yib yuborildi.";
break;
}
}
}
let menu = new Menu();
elem.addEventListener('mousedown', menu);
elem.addEventListener('mouseup', menu);
</script>
Bu yerda bir xil obyekt ikkala hodisani qayta ishlaydi. Diqqat qiling, biz addEventListener
yordamida tinglash uchun hodisalarni aniq o’rnatishimiz kerak. menu
obyekti faqat mousedown
va mouseup
ni oladi, boshqa turdagi hodisalarni emas.
handleEvent
metodi barcha ishni o’zi qilishi shart emas. U o’rniga hodisaga xos boshqa metodlarni chaqirishi mumkin:
<button id="elem">Menga bosing</button>
<script>
class Menu {
handleEvent(event) {
// mousedown -> onMousedown
let method = 'on' + event.type[0].toUpperCase() + event.type.slice(1);
this[method](event);
}
onMousedown() {
elem.innerHTML = "Sichqoncha tugmasi bosildi";
}
onMouseup() {
elem.innerHTML += "...va qo'yib yuborildi.";
}
}
let menu = new Menu();
elem.addEventListener('mousedown', menu);
elem.addEventListener('mouseup', menu);
</script>
Endi hodisa ishlov beruvchilari aniq ajratildi, uni qo’llab-quvvatlash osonroq bo’lishi mumkin.
Xulosa
Hodisa ishlov beruvchilarni tayinlashning 3 usuli bor:
- HTML atributi:
onclick="..."
. - DOM xossasi:
elem.onclick = function
. - Metodlar: qo’shish uchun
elem.addEventListener(event, handler[, phase])
, olib tashlash uchunremoveEventListener
.
HTML atributlari kamdan-kam ishlatiladi, chunki HTML tegi o’rtasidagi JavaScript biroz g’alati va begona ko’rinadi. Shuningdek, u yerda ko’p kod yozib bo’lmaydi.
DOM xossalarini ishlatish yaxshi, lekin biz ma’lum hodisaning birdanortiq ishlov beruvchisini tayinlay olmaymiz. Ko’p hollarda bu cheklov bosim o’tkazmaydi.
Oxirgi usul eng moslashuvchan, lekin u ham eng uzun yoziladi. Faqat u bilan ishlaydigan kam hodisalar bor, masalan transitionend
va DOMContentLoaded
(ko’rib chiqiladi). Shuningdek addEventListener
hodisa ishlov beruvchilari sifatida obyektlarni qo’llab-quvvatlaydi. Bunday holda hodisa holatida handleEvent
metodi chaqiriladi.
Ishlov beruvchini qanday tayinlashingizdan qat’i nazar – u birinchi argument sifatida hodisa obyektini oladi. Bu obyekt nima sodir bo’lganligi haqidagi tafsilotlarni o’z ichiga oladi.
Keyingi boblarda biz hodisalar haqida umumiy va turli xil hodisa turlari haqida ko’proq o’rganamiz.
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…)