Mundarija (35)
- Bu darsda
- 1. Nega bu kerak?
- 2. Hodisa obyekti
- 2.1 Handler argument oladi
- 2.2 Har hodisa turi — o'z obyekti
- 3. target va currentTarget
- 3.1 Ichida boshqa element bo'lgan tugma
- 3.2 Farqi qanday eslab qolinadi
- 3.3 Tuzoq: currentTarget keyin null bo'ladi
- 4. timeStamp va isTrusted
- 4.1 timeStamp — hodisa qachon bo'ldi
- 4.2 isTrusted — odammi yoki skript?
- 5. Standart harakatlar
- 5.1 Brauzer o'zi nima qiladi?
- 5.2 Havola ochilmasin
- 5.3 Forma yuborilmasin
- 5.4 Checkbox — g'alati, lekin mantiqiy
- 5.5 Har harakatni to'xtatib bo'lmaydi
- 5.6 aria-disabled tugma: va'da bajarildi
- 5.7 return false — eski usul
- 6. Hujumchi nigohi
- 7. Ko'p uchraydigan xatolar
- 7.1 preventDefault qavssiz
- 7.2 Forma tugmasining click iga qo'yish
- 7.3 target ni element deb o'ylash
- 7.4 Kechikkan currentTarget
- 7.5 Hamma narsani preventDefault qilish
- 8. Mashqlar
- 1-mashq (oson): Telefon havolasi
- 2-mashq (o'rta): Ism bo'sh bo'lmasin
- 3-mashq (qiyin): Ikki marta bosishdan himoya
- 4-mashq: Portfolio qadami — joriy sahifa havolasi qayta yuklamasin
- 9. Real ishda
- Xulosa
- Manbalar
JavaScript event obyekti: target, currentTarget va preventDefault
Qisqacha: Brauzer har handlerga hodisa haqidagi obyektni argument qilib beradi:
tugma.addEventListener("click", (event) => {...}). Unda hodisa turi (type), bosilgan eng ichki element (target) va tinglovchi turgan element (currentTarget) bor. Vaqt (timeStamp) va "haqiqiy foydalanuvchidanmi?" (isTrusted) degan ma'lumotlar ham bor.event.preventDefault()brauzerning standart harakatini bekor qiladi: havola ochilmaydi, forma yuborilmaydi.
Bu darsda
- Handlerga keladigan hodisa obyektini olib, uning asosiy xususiyatlarini o'qiy olasiz.
targetvacurrentTargetfarqini tushuntira olasiz va qaysi biri qachon kerakligini bilasiz.timeStampvaisTrustednima uchun kerakligini bilasiz.- Havola, forma va checkbox'ning standart harakatini
preventDefaultbilan to'xtata olasiz. preventDefaultnima qilmasligini va nega u xavfsizlik vositasi emasligini bilasiz.
Oldin bilishingiz kerak: addEventListener asoslari, Forma qanday ishlaydi.
1. Nega bu kerak?
O'tgan darsda tugma bosilganda kod ishlatdik. Lekin handler juda kam narsa bilardi: "nimadir bosildi" — xolos. Qayeri bosildi? Qachon? Odam bosdimi yoki skript? Bularni bilmasak, ko'p ish qilib bo'lmaydi.
Ikkinchi muammo — jiddiyroq. «Bahor»ning bron formasini olaylik. Mehmon «Yuborish» ni bosadi va brauzer darhol formani serverga jo'natadi, sahifa almashadi. Biz esa avval tekshirmoqchimiz: ism yozilganmi, sana to'g'rimi? Brauzerga "to'xta, avval men" deyish kerak.
Hayotdan o'xshatish: pochtachi eshik qo'ng'irog'ini bosdi. Otabek eshikka borganda pochtachi unga xat beradi: kimdan, qachon jo'natilgan, kimga. Bu — hodisa obyekti. Xatni o'qib, Otabek qaror qiladi: odatdagidek qabul qiladimi yoki "bu bizga emas" deb qaytaradimi. Qaytarish — standart harakatni bekor qilish.
2. Hodisa obyekti
2.1 Handler argument oladi
Brauzer handlerni chaqirganda unga bitta argument beradi — hodisa haqidagi obyekt. Uni olish uchun funksiyaga parametr yozish kifoya:
<button id="savatga" type="button">Savatga</button>
<script>
const tugma = document.getElementById("savatga");
tugma.addEventListener("click", (event) => {
console.log(event);
console.log(event.type);
});
</script>Bosing. Konsolda ikki qator chiqadi:
PointerEvent {type: 'click'}— hodisa obyektining o'zi. UPointerEventturidagi obyekt.click— uningtypexususiyati.
Parametr nomi istalgancha bo'lishi mumkin. O'tgan darsda kelishganimizdek, biz uni event deb yozamiz — MDN va ish joyidagi kodlardagi kabi (ba'zan qisqa e ham uchraydi). Matnda esa tushunchaning o'zbekcha nomini ishlatamiz: hodisa obyekti.
Jonli oynadagi konsol obyektni bitta qatorda qisqa ko'rsatadi. Chrome DevTools'da esa uning yonida uchburchak bor: bossangiz, ichidagi o'nlab xususiyat ochiladi. Ularning ko'pini keyingi darslarda alohida o'rganamiz.
2.2 Har hodisa turi — o'z obyekti
Hodisa obyekti hodisaga qarab har xil turda bo'ladi. Hammasida umumiy xususiyatlar bor (type, target...), lekin har birida o'ziga xoslari ham bor:
| Hodisa | Obyekt turi | O'ziga xos ma'lumot | Darsi |
|---|---|---|---|
click |
PointerEvent |
qayerda bosildi, sichqonchami yoki barmoq | Pointer |
keydown |
KeyboardEvent |
qaysi tugma bosildi | Klaviatura |
submit |
SubmitEvent |
qaysi tugma formani yubordi | Forma |
DOMContentLoaded |
Event |
faqat umumiylar | Brauzer muhiti |
PointerEvent — eski MouseEvent (sichqoncha hodisasi) ning kengaytirilgan varianti: sichqonchaning hamma xususiyati unda ham bor. Chrome'da click — PointerEvent; ba'zi brauzerlarda u MouseEvent bo'lib keladi. Ma'nosi bir xil.
Bitta handler bir nechta hodisa turiga xizmat qilsa, type ular orasini ajratadi. Masalan, tugmani bir marta va ikki marta tez bosishni kuzataylik:
<button id="osh" type="button">Osh</button>
<script>
function kuzat(event) {
console.log(event.type);
}
const tugma = document.getElementById("osh");
tugma.addEventListener("click", kuzat);
tugma.addEventListener("dblclick", kuzat);
</script>Tugmani ikki marta tez bosing (telefonda — ikki marta tez teging). Konsolda uch qator chiqadi: click, click, dblclick. Biz buni Chrome'da tekshirdik. Ajablanarli tomoni: dblclick dan oldin ikkita oddiy click keladi. Demak bitta tugmaga ham click, ham dblclick qo'ysangiz, ikki marta bosishda click handleri ham ikki marta ishlaydi. Bunday tugmalar chalkashtiradi — kamdan-kam qiling.
Tekshirib ko'ring:
tugma.addEventListener("click", () => console.log(event.type))— arrow funksiyada parametr yozilmagan. Bu kod ishlaydimi?
Javob
Chrome'da ishlaydi va click chiqaradi — lekin tasodifan. Parametr yo'q, shuning uchun bu yerdagi event — brauzerning eskirgan global xususiyati window.event: u "hozir ishlanayotgan hodisa"ni saqlaydi. Unga tayanmang: u eskirgan (deprecated), Node'da umuman yo'q, kodni o'qigan odam esa event qayerdan kelganini tushunmaydi. Tuzatish: parametrni doim yozing — (event) => console.log(event.type).
3. target va currentTarget
3.1 Ichida boshqa element bo'lgan tugma
Ko'p tugmaning ichida ikonka yoki alohida matn bo'ladi. «Savatga» tugmasining ichida + belgisi span da turibdi. Mehmon aynan + ning ustidan bossa-chi?
<button id="savatga" type="button">
<span class="ikonka">+</span> Savatga
</button>
<script>
const tugma = document.getElementById("savatga");
tugma.addEventListener("click", (event) => {
console.log("target:", event.target);
console.log("currentTarget:", event.currentTarget);
});
</script>Avval + belgisining ustidan bosing. Konsolda:
target: <span class="ikonka">+</span>— bosish aynan shuspanga tushdi;currentTarget: <button id="savatga" type="button">…</button>— tinglovchi esa tugmada.
Endi "Savatga" so'zining ustidan bosing: ikkala qatorda ham tugma chiqadi. So'z alohida elementda emas, u tugmaning o'z matni.
3.2 Farqi qanday eslab qolinadi
target(nishon) — hodisa qayerda boshlandi: bosilgan eng ichki element.currentTarget(joriy nishon) — tinglovchi qayerda turibdi: bizaddEventListenerni chaqirgan element.
O'xshatish: Otabek «Bahor»ning kassasida turibdi va "Kassaga keling" deb e'lon qilgan (tinglovchi — kassada). Mehmon esa 5-stoldan qo'l ko'tardi. Mehmon turgan joy — target (5-stol), xabar yetib kelgan joy — currentTarget (kassa).
Ichi bosilsa ham tinglovchi nega ishladi? Biz tinglovchini span ga qo'ymagan edik. Sababi — hodisa ichki elementdan tashqariga qarab "ko'tariladi". Buni keyingi darsda to'liq ko'ramiz. Hozircha qoida: handlerda elementning o'zi kerak bo'lsa — currentTarget. target ichki span, svg yoki matnni o'rab turgan teg bo'lib chiqishi mumkin.
O'tgan darsda aytganimizdek, currentTarget handlerdagi this ning ishonchli o'rnini bosadi: u arrow funksiyada ham to'g'ri ishlaydi.
3.3 Tuzoq: currentTarget keyin null bo'ladi
currentTarget faqat handler ishlab turgan paytda to'ldiriladi. Brauzer handlerdan chiqqach uni tozalaydi. Keyinroq o'qisangiz — null:
<button id="savatga" type="button">
<span class="ikonka">+</span> Savatga
</button>
<script>
const tugma = document.getElementById("savatga");
tugma.addEventListener("click", (event) => {
setTimeout(() => {
console.log("keyin:", event.currentTarget);
console.log("keyin:", event.target);
}, 0);
});
</script>+ ustidan bosing. Konsolda: keyin: null, keyin keyin: <span class="ikonka">+</span>. setTimeout funksiyani handler tugagach chaqiradi (Callback darsida ko'rgansiz) — o'sha paytda currentTarget allaqachon bo'sh. target esa saqlanib qoladi.
Qoida: keyinroq kerak bo'ladigan elementni handler boshidayoq o'zgaruvchiga oling: const tugma = event.currentTarget;. Bu tuzoq asinxron kodda — server javobini kutganda — tez-tez uchraydi. Asinxronlikni 11-qismda o'rganamiz.
Tekshirib ko'ring:
ulgaclicktinglovchisi qo'yildi. Mehmon ikkinchilini bosdi.event.targetvaevent.currentTargetnima bo'ladi?
Javob
target — bosilgan li (agar uning ichida boshqa element bo'lmasa), currentTarget — ul, chunki tinglovchi o'sha yerda. Aynan shu farq Event delegation naqshining asosi: bitta tinglovchi ul da, qaysi li bosilganini esa target aytadi.
4. timeStamp va isTrusted
4.1 timeStamp — hodisa qachon bo'ldi
timeStamp — sahifa ochilgandan beri o'tgan vaqt, millisekundda (soniyaning mingdan biri). Masalan 5234.6 — sahifa ochilganiga taxminan 5,2 soniya bo'lgan. Uning aniq qiymati har safar boshqacha, shuning uchun bitta qiymatning o'zi kam qiziq. Foydasi — ikki hodisa orasidagi farqda:
<button id="choy" type="button">Ko'k choy</button>
<script>
const tugma = document.getElementById("choy");
let oldingi = 0;
tugma.addEventListener("click", (event) => {
if (oldingi !== 0) {
const oraliq = Math.round(event.timeStamp - oldingi);
console.log(`Oldingi bosishdan beri: ${oraliq} ms`);
}
oldingi = event.timeStamp;
});
</script>Tugmani bir necha marta bosing. Birinchi bosishda konsol jim, keyin har bosishda Oldingi bosishdan beri: 412 ms kabi qator chiqadi. Son sizning tezligingizga bog'liq. Math.round — Math obyekti darsidan.
Real ishda bu nimaga kerak? "Juda tez ketma-ket bosish"ni aniqlash uchun: mehmon «Buyurtma berish» ni sabrsizlanib uch marta bosdi — uchta buyurtma ketmasin. Bunday himoyaning tayyor qoliplarini (debounce, throttle) Debounce va throttle darsida o'rganamiz.
4.2 isTrusted — odammi yoki skript?
Hodisani foydalanuvchi emas, kod ham yaratishi mumkin. Eng oddiy yo'l — elementning click() metodi: u tugmani "bosgandek" qiladi:
<button id="osh" type="button">Osh</button>
<button id="robot" type="button">Skript bossin</button>
<script>
const osh = document.getElementById("osh");
osh.addEventListener("click", (event) => {
console.log("isTrusted:", event.isTrusted);
});
document.getElementById("robot").addEventListener("click", () => {
osh.click();
});
</script>«Osh» ni o'zingiz bosing — isTrusted: true. «Skript bossin» ni bosing — u kod bilan osh.click() ni chaqiradi va konsolda isTrusted: false chiqadi. Klaviatura bilan bosish (Tab → Enter) ham true beradi — u ham haqiqiy foydalanuvchi harakati.
isTrusted ni sahifadagi skript soxtalashtira olmaydi. Lekin buni himoya deb o'ylamang. Brauzer kengaytmalari va avtomatik test vositalari (masalan, Chrome'ni kod bilan boshqaradigan Puppeteer) brauzerning o'zi orqali bosadi — ularning hodisasi ham isTrusted: true. Shuning uchun isTrusted foydali signal, lekin "bot emas" degan kafolat emas.
O'z hodisalaringizni yaratish va yuborish (dispatchEvent) — Custom events darsida.
5. Standart harakatlar
5.1 Brauzer o'zi nima qiladi?
Ko'p elementda standart harakat (default action) bor — brauzer hech qanday JavaScript'siz, o'zi bajaradigan ish:
| Harakat | Standart harakat |
|---|---|
| Havolani bosish | href dagi manzilga o'tish |
Formada «Yuborish» yoki maydonda Enter |
formani action ga jo'natish |
| Checkbox'ni bosish | belgini qo'yish yoki olib tashlash |
label ni bosish |
bog'langan maydonga fokus |
| O'ng tugma | kontekst menyusi |
| Sichqoncha g'ildiragi | sahifani surish |
Bular HTML qismidan tanish (Forma qanday ishlaydi, Tugmalar va yuborish). Endi yangi narsa: tinglovchi standart harakatdan oldin ishlaydi va uni bekor qila oladi. Tartib shunday:
flowchart TD
A["Mehmon bosdi"] --> B["Brauzer hodisa obyektini yaratdi"]
B --> C["Hamma tinglovchilar ishladi"]
C --> D{"preventDefault() chaqirildimi?"}
D -->|ha| E["Standart harakat bekor"]
D -->|yo'q| F["Brauzer standart harakatni bajaradi"]Diagrammadagi asosiy fikr: brauzer avval hamma tinglovchini ishlatadi, keyin qaror qiladi. Shuning uchun preventDefault() handlerning boshida ham, oxirida ham yozilsa bir xil ishlaydi.
5.2 Havola ochilmasin
<a id="menyu" href="https://example.com/menyu">Menyuni ochish</a>
<p id="holat"></p>
<script>
const havola = document.getElementById("menyu");
havola.addEventListener("click", (event) => {
event.preventDefault();
document.getElementById("holat").textContent =
"Menyu shu sahifada ochildi (namoyish)";
});
</script>Havolani bosing — boshqa sahifaga o'tilmaydi, ostida matn chiqadi. Bu qolip "sahifani almashtirmay, kontentni shu yerda ko'rsatish" uchun ishlatiladi: tablar, modal oyna, bir sahifali ilovalar.
Diqqat: "Tahrirlab ko'rish" bilan
preventDefault()qatorini o'chirib bossangiz, bu oynada farq ko'rinmaydi: matn baribir chiqadi, sahifa joyida qoladi. Jonli oyna begona saytga ketib qolmasligi uchun havolani eng oxirgi lahzada o'zi to'xtatadi — lekin faqat sizning kodingiz to'xtatmagan bo'lsa. Haqiqiy sahifada esa matn bir lahza chiqib, brauzer darholexample.com/menyuga o'tib ketardi. Buni o'z saytingizda Live Server bilan sinang.
Bitta ogohlantirish: havolaning ishini to'xtatib, uni tugmaga aylantirmang. Havola — boshqa joyga olib boradi, tugma — shu yerda ish qiladi (Tugma yoki havola). Eski va yomon odat — href="#" va preventDefault bilan "tugma" yasash: Malika NVDA'da "havola" ni eshitadi va boshqa sahifa ochiladi deb kutadi. Ish shu yerda bajarilsa — <button>.
5.3 Forma yuborilmasin
Eng ko'p ishlatiladigan holat — forma. Bu yerda bitta muhim tafsilot bor: tinglovchi formaning submit hodisasiga qo'yiladi, tugmaning click iga emas.
<form id="bron" action="https://example.com/bron" method="post">
<label for="ism">Ismingiz</label>
<input id="ism" name="ism">
<button>Stol band qilish</button>
</form>
<p id="holat"></p>
<script>
const forma = document.getElementById("bron");
forma.addEventListener("submit", (event) => {
event.preventDefault();
console.log(event);
const ism = document.getElementById("ism").value;
document.getElementById("holat").textContent =
`Rahmat, ${ism}! Bron qabul qilindi (namoyish)`;
});
</script>Ismni yozing va tugmani bosing — sahifa almashmaydi, ostida xabar chiqadi, konsolda SubmitEvent {type: 'submit'}. Endi maydonga qayting va Enter ni bosing — natija xuddi shunday. Biz buni Chrome'da tekshirdik.
Nega submit, click emas? Formani yuborishning bir necha yo'li bor: tugmani bosish, maydonda Enter, klaviatura bilan tugmaga borib Bo'sh joy. submit hodisasi hammasida keladi. Tugmaning click iga qo'ysangiz, ba'zi yo'llarni unutib qo'yasiz.
value — maydonga yozilgan matn. Uni va forma bilan ishlashning boshqa usullarini Forma qiymatlarini o'qish darsida o'rganamiz. event.submitter — formani qaysi tugma yuborganini ko'rsatadi; ikki tugmali formada ("Saqlash" va "Qoralama") kerak bo'ladi.
Tekshirib ko'ring: Formada «Yuborish» tugmasi bor. Dasturchi
tugma.addEventListener("click", ...)ichidapreventDefault()chaqirdi. Mehmon ismni yozibEnterbosdi. Forma yuboriladimi?
Javob
Yo'q, yuborilmaydi — Chrome'da sinadik. Maydonda Enter bosilganda brauzer yuborish tugmasini "bosgandek" qiladi: tugmada click hodisasi chiqadi, keyin submit. click bekor qilingani uchun yuborish ham to'xtadi. Lekin bu ayyor bog'liqlik — formani boshqarish uchun baribir submit ishlating: niyatingiz kodda aniq ko'rinadi.
5.4 Checkbox — g'alati, lekin mantiqiy
Checkbox'ning standart harakati — belgini almashtirish. preventDefault uni to'xtatadi, lekin bitta ajablanarli tafsilot bor:
<label>
<input id="yetkazish" type="checkbox"> Uyga yetkazib berish
</label>
<p id="izoh"></p>
<script>
const belgi = document.getElementById("yetkazish");
belgi.addEventListener("click", (event) => {
event.preventDefault();
console.log("handler ichida:", belgi.checked);
document.getElementById("izoh").textContent =
"Yetkazib berish bugun ishlamaydi";
});
</script>Bosing. Konsolda handler ichida: true, lekin ekranda belgi qo'yilmagan — u bo'sh qoldi. Nega true? Brauzer checkbox'ni avval "sinov uchun" almashtiradi, keyin handlerni chaqiradi. preventDefault chaqirilgani uchun handlerdan keyin almashtirishni qaytaradi. Shu sabab handler ichidagi checked ga ishonib bo'lmaydi.
Real loyihada mavjud bo'lmagan imkoniyatni to'xtatishning to'g'ri yo'li — disabled atributi yoki tushuntirish matni. Bu misol faqat standart harakat qanday ishlashini ko'rsatadi.
5.5 Har harakatni to'xtatib bo'lmaydi
Ba'zi hodisalarning standart harakati yo'q yoki uni bekor qilib bo'lmaydi. Buni cancelable xususiyati aytadi. defaultPrevented esa "kimdir allaqachon preventDefault chaqirdimi?" degan savolga javob beradi:
<input id="ism" aria-label="Ism">
<script>
const maydon = document.getElementById("ism");
maydon.addEventListener("input", (event) => {
event.preventDefault();
console.log(event.cancelable, event.defaultPrevented);
});
</script>Maydonga harf yozing. Har harfda konsolda false false chiqadi — va harf baribir yozildi. input hodisasi harf qo'shilgandan keyin keladi: to'xtatadigan narsa qolmagan. Xususiyat cancelable: false — "bekor qilib bo'lmaydi", shuning uchun preventDefault jim e'tiborsiz qoldi.
Harf yozilishini oldindan to'xtatish kerak bo'lsa, boshqa hodisalar bor: keydown (Klaviatura hodisalari darsida) va beforeinput — u harf qo'shilishidan oldin keladi. Yozilgan qiymat bilan ishlash esa — input va change darsida. Xuddi shunday, scroll hodisasi ham surilgandan keyin keladi — u ham bekor qilinmaydi (Fokus, scroll va resize).
5.6 aria-disabled tugma: va'da bajarildi
O'tgan darsda aria-disabled tugmani return bilan to'xtatdik va "formada bu yetmaydi" dedik. Mana yechim:
<form id="bron" action="https://example.com/bron" method="post">
<label for="sana">Sana</label>
<input id="sana" name="sana" type="date">
<button id="yubor" aria-disabled="true"
aria-describedby="sabab">Yuborish</button>
<p id="sabab">Avval sanani tanlang</p>
</form>
<script>
const tugma = document.getElementById("yubor");
tugma.addEventListener("click", (event) => {
if (tugma.getAttribute("aria-disabled") === "true") {
event.preventDefault();
console.log("Yuborish to'xtatildi");
}
});
</script>«Yuborish» ni bosing — konsolda "Yuborish to'xtatildi", forma ketmaydi. Bu yerda click to'g'ri tanlov: biz formani emas, aynan shu tugmani "o'chirilgan" qilmoqchimiz. Sana tanlanganda aria-disabled ni false ga almashtirish uchun maydonning change hodisasi kerak — uni input va change darsida o'rganamiz.
5.7 return false — eski usul
Eski kodlarda shunday yozuvni ko'rasiz:
havola.onclick = () => {
return false; // standart harakat bekor bo'ladi
};onclick xususiyati yoki atributida return false haqiqatan preventDefault vazifasini bajaradi. Lekin addEventListener da u ishlamaydi: brauzer qaytgan qiymatga qaramaydi. Biz ikkalasini Chrome'da sinadik — xususiyatdagi havola ochilmadi, addEventListener dagisi esa ochildi. Chalkashmaslik uchun hamma joyda preventDefault() yozing.
6. Hujumchi nigohi
preventDefault, aria-disabled tekshiruvi va isTrusted — hammasi mehmonning brauzerida ishlaydi. Brauzer esa mehmonning qo'lida. Faraz qiling, bron formasi "20 kishidan ko'p bo'lmasin" degan tekshiruvni faqat JavaScript'da qiladi. Hujumchi nima qiladi?
- DevTools'da
aria-disabledni o'chiradi yoki tinglovchini olib tashlaydi (Event Listeners tabida "Remove" tugmasi bor). - JavaScript'ni butunlay o'chirib qo'yadi — forma oddiy HTML forma bo'lib yuboriladi.
- Brauzersiz, to'g'ridan-to'g'ri
https://example.com/bronga so'rov yuboradi (terminaldagicurlbilan — Tarmoqni terminaldan tekshirish darsidagidek). Hech qanday sahifa, hech qanday tinglovchi yo'q.
Xulosa: brauzerdagi tekshiruv — qulaylik uchun. U mehmonga xatoni tez ko'rsatadi va serverni bo'sh so'rovlardan asraydi. Himoya esa faqat serverda bo'ladi: server har so'rovni o'zi qayta tekshiradi. Buni backend qismida quramiz. Hozircha qoida: "JavaScript to'xtatdi — demak hech kim yubora olmaydi" deb hech qachon o'ylamang.
7. Ko'p uchraydigan xatolar
7.1 preventDefault qavssiz
event.preventDefault; — xato chiqmaydi, lekin hech narsa bo'lmaydi. Bu metodni chaqirish emas, shunchaki uni o'qish. To'g'risi: event.preventDefault();.
7.2 Forma tugmasining click iga qo'yish
Forma Enter bilan ham yuboriladi. Formani tekshirish — form ning submit hodisasida. Tugmaning click i faqat o'sha tugmaning o'ziga tegishli ish uchun («aria-disabled» bo'limidagi kabi).
7.3 target ni element deb o'ylash
Tugma ichida ikonka bo'lsa, event.target.id bo'sh satr qaytaradi — bosilgan narsa span. Tinglovchi qo'yilgan element kerak bo'lsa — currentTarget.
7.4 Kechikkan currentTarget
setTimeout ichida yoki serverni kutgandan keyin event.currentTarget — null. Kerakli elementni handler boshida o'zgaruvchiga oling.
7.5 Hamma narsani preventDefault qilish
O'ng tugma menyusini (contextmenu) yoki matnni nusxalashni to'xtatish texnik jihatdan mumkin. Lekin bu mehmonni g'azablantiradi va himoya bermaydi: matnni baribir "Sahifa kodini ko'rish" orqali olish mumkin. Standart harakatni faqat uning o'rniga yaxshiroq narsa taklif qilganda to'xtating.
8. Mashqlar
1-mashq (oson): Telefon havolasi
«Qo'ng'iroq qilish» havolasi tel: bilan yozilgan. Kompyuterda u odatda hech narsa qilmaydi yoki notanish dastur ochiladi. Havolaga tinglovchi qo'ying: preventDefault bilan to'xtatib, #raqam paragrafiga "Telefon: +998 90 000 00 00" yozilsin.
<a id="qongiroq" href="tel:+998900000000">Qo'ng'iroq qilish</a>
<p id="raqam"></p>
<script>
// shu yerga yozing
</script>Yechim
<a id="qongiroq" href="tel:+998900000000">Qo'ng'iroq qilish</a>
<p id="raqam"></p>
<script>
const havola = document.getElementById("qongiroq");
havola.addEventListener("click", (event) => {
event.preventDefault();
document.getElementById("raqam").textContent =
"Telefon: +998 90 000 00 00";
});
</script>Real saytda bunday qilmang: telefonda tel: havolasi raqamni darhol teradi — bu juda qulay. Mashq faqat preventDefault ni havolada sinash uchun. To'g'ri yechim — raqamni doim ko'rinadigan matn bilan yozish.
2-mashq (o'rta): Ism bo'sh bo'lmasin
Bron formasi yuborilganda: ism bo'sh bo'lsa (yoki faqat bo'sh joylar) — #xato ga "Ismingizni yozing" chiqsin; bo'lmasa — #xato tozalansin va #holat ga "Rahmat, Ali!" kabi xabar chiqsin. Ikkala holatda ham forma haqiqatan yuborilmasin (bu namoyish — server yo'q). Bo'sh joylarni trim() bilan olib tashlang (Matnni tozalash).
<form id="bron" action="https://example.com/bron" method="post">
<label for="ism">Ismingiz</label>
<input id="ism" name="ism">
<button>Yuborish</button>
<p id="xato"></p>
</form>
<p id="holat"></p>
<script>
// shu yerga yozing
</script>Yechim
<form id="bron" action="https://example.com/bron" method="post">
<label for="ism">Ismingiz</label>
<input id="ism" name="ism">
<button>Yuborish</button>
<p id="xato"></p>
</form>
<p id="holat"></p>
<script>
const forma = document.getElementById("bron");
const xato = document.getElementById("xato");
const holat = document.getElementById("holat");
forma.addEventListener("submit", (event) => {
event.preventDefault();
const ism = document.getElementById("ism").value.trim();
if (ism === "") {
xato.textContent = "Ismingizni yozing";
holat.textContent = "";
return;
}
xato.textContent = "";
holat.textContent = `Rahmat, ${ism}!`;
});
</script>Bo'sh maydon bilan yuboring — xato chiqadi. Faqat bo'sh joy yozing — yana xato (trim ularni olib tashladi). "Ali" yozing — "Rahmat, Ali!". preventDefault boshida — shunda har qanday holatda forma ketmaydi. Haqiqiy loyihada to'g'ri ma'lumotda preventDefault chaqirilmaydi va forma serverga jo'naydi. Xatoni qulay ko'rsatish (maydon yonida, ekran o'quvchiga ham) — Constraint Validation API va Dinamik UI'da qulaylik darslarida.
3-mashq (qiyin): Ikki marta bosishdan himoya
«Buyurtma berish» tugmasi bor. Mehmon uni sabrsizlanib tez-tez bosadi. Talab: oldingi qabul qilingan bosishdan 1000 ms o'tmagan bo'lsa, bosish e'tiborsiz qolsin va konsolga "Juda tez — kuting" chiqsin. Aks holda — "Buyurtma №1 qabul qilindi", "Buyurtma №2 ...". Vaqtni event.timeStamp bilan o'lchang.
<button id="buyurtma" type="button">Buyurtma berish</button>
<script>
// shu yerga yozing
</script>Ishora: ikki o'zgaruvchi kerak — buyurtmalar soni va oxirgi qabul qilingan bosishning vaqti. Birinchi bosish doim qabul qilinsin.
Yechim
<button id="buyurtma" type="button">Buyurtma berish</button>
<script>
const tugma = document.getElementById("buyurtma");
let soni = 0;
let oxirgi = -Infinity;
tugma.addEventListener("click", (event) => {
if (event.timeStamp - oxirgi < 1000) {
console.log("Juda tez — kuting");
return;
}
oxirgi = event.timeStamp;
soni++;
console.log(`Buyurtma №${soni} qabul qilindi`);
});
</script>Tugmani tez-tez uch marta bosing: "Buyurtma №1 qabul qilindi", keyin ikki marta "Juda tez — kuting". Bir soniya kuting va yana bosing — "Buyurtma №2 qabul qilindi".
oxirgi = -Infinity — hiyla: istalgan son minus "manfiy cheksizlik" — cheksiz katta son, shuning uchun birinchi bosish doim o'tadi (Infinity). Agar oxirgi = 0 yozsangiz, u ham deyarli doim ishlaydi, lekin sahifa ochilgan zahoti birinchi soniyada bosilsa, birinchi bosish ham "juda tez" bo'lib qolardi.
oxirgi faqat qabul qilingan bosishda yangilanadi. Uni har bosishda yangilasangiz, tinimsiz bosayotgan mehmon hech qachon o'tolmaydi. Bu himoya ham faqat qulaylik uchun — server baribir bir xil buyurtmalarni o'zi tekshiradi («Hujumchi nigohi» bo'limi).
4-mashq: Portfolio qadami — joriy sahifa havolasi qayta yuklamasin
Telefonda mehmon "Aloqa" sahifasida turibdi, menyuni ochib yana "Aloqa" ni bosdi. Brauzer o'sha sahifani qaytadan yuklaydi: sekin internetda bir necha soniya oq ekran, o'qigan joyi yo'qoladi. Foyda — nol. Joriy sahifa havolasi aria-current="page" bilan belgilangan (Atributlar va dataset darsida JavaScript buni tekshiradigan ham bo'ldi).
addEventListener asoslari darsidagi menyu siklini kengaytiring:
- Handler hodisa obyektini olsin.
- Bosilgan havola joriy sahifaniki bo'lsa — standart harakatni bekor qiling (sahifa qayta yuklanmasin).
- Panel har holda yopilsin (avvalgidek).
Havolani handler ichida ikki xil olish mumkin: sikl o'zgaruvchisi (havola) yoki event.currentTarget. Ikkinchisini ishlating — handler tashqi o'zgaruvchiga bog'lanmasin.
Yechim
asosiy.js dagi menyu qismi:
// Telefon menyusi: havola bosilganda panel yopilsin,
// joriy sahifa havolasi sahifani qayta yuklamasin
const menyu = document.getElementById("asosiy-menyu");
if (menyu !== null) {
for (const havola of menyu.querySelectorAll("a")) {
havola.addEventListener("click", (event) => {
const bosilgan = event.currentTarget;
if (bosilgan.getAttribute("aria-current") === "page") {
event.preventDefault();
}
menyu.hidePopover();
});
}
}Menyuga o'xshash parchada sinang. Bu yerda faqat sinov uchun boshqa havolalar ham to'xtatiladi — jonli oyna begona sahifaga o'tib ketmasin:
<button type="button" popovertarget="asosiy-menyu">Menyu</button>
<nav id="asosiy-menyu" aria-label="Asosiy menyu" popover>
<ul>
<li><a href="https://example.com/">Bosh sahifa</a></li>
<li>
<a href="https://example.com/aloqa/" aria-current="page">
Aloqa
</a>
</li>
</ul>
</nav>
<script>
const menyu = document.getElementById("asosiy-menyu");
if (menyu !== null) {
for (const havola of menyu.querySelectorAll("a")) {
havola.addEventListener("click", (event) => {
const bosilgan = event.currentTarget;
if (bosilgan.getAttribute("aria-current") === "page") {
event.preventDefault();
}
console.log("Bekor qilindi:", event.defaultPrevented);
event.preventDefault(); // faqat sinov uchun
menyu.hidePopover();
});
}
}
</script>«Menyu» → "Aloqa": panel yopiladi, konsolda "Bekor qilindi: true" — bu joriy sahifa. «Menyu» → "Bosh sahifa": "Bekor qilindi: false" — haqiqiy saytda bu havola odatdagidek ochiladi.
Malika uchun hech narsa o'zgarmadi: NVDA havolani baribir "Aloqa, joriy sahifa, havola" deb o'qiydi, aria-current HTML'da qoladi. Kompyuterda ham xuddi shunday ishlaydi — joriy sahifa havolasi endi bekorga qayta yuklamaydi.
Tekshiring: Live Server'da "Aloqa" sahifasida menyudagi "Aloqa" ni bosing — Network panelida yangi so'rov yo'q. "Bosh sahifa" ni bosing — odatdagidek o'tadi. npm run check, commit: JS: joriy sahifa havolasi qayta yuklamasin.
9. Real ishda
- Bir sahifali ilovalar (Telegram Web, Gmail, kursimizdagi
vazifalarilovasi) deyarli har havola va formadapreventDefaultqiladi: sahifani almashtirmay, kontentni JavaScript bilan chizadi. React kabi freymvorklarning yo'naltirgichlari (router — kursda alohida o'rganamiz) aynan shu ustiga qurilgan. - Formalar — har to'lov, ro'yxatdan o'tish va izoh formasi
submit+preventDefault+ server so'rovi bilan ishlaydi. Click va Payme sahifalaridagi tugmalarning "ikki marta bosishdan himoyasi" —timeStampyoki shunga o'xshash qoliplar. - Analitika
isTrustedvatimeStampdan foydalanadi: haqiqiy bosishlar, reaksiya vaqti. - Intervyuda klassik savollar: "
targetvacurrentTargetfarqi?", "preventDefaultvastopPropagationfarqi?" — ikkinchisining javobi keyingi darsda.
Xulosa
- Handler argument oladi — hodisa obyekti (
PointerEvent,SubmitEvent...). Undatype,target,currentTarget,timeStamp,isTrusted. target— hodisa boshlangan eng ichki element,currentTarget— tinglovchi turgan element. Elementning o'zi kerak bo'lsa —currentTarget.currentTargethandler tugagachnullbo'ladi — kerak bo'lsa oldindan saqlang.preventDefault()standart harakatni bekor qiladi: havola ochilmaydi, forma ketmaydi. U hamma tinglovchidan keyin hal qilinadi.- Formani
submithodisasida boshqaring;cancelable: falsehodisani to'xtatib bo'lmaydi. - Brauzerdagi to'xtatish — qulaylik, himoya emas: server har so'rovni o'zi tekshiradi.
Keyingi dars: Hodisa tarqalishi: capture va bubble — nega span ustidan bosganda tugmaning tinglovchisi ishladi: hodisaning daraxt bo'ylab sayohatini kuzatamiz.
Manbalar
- MDN: "Event", "Event: target property", "Event: currentTarget property" — developer.mozilla.org
- MDN: "Event: preventDefault() method", "Event: isTrusted property", "Event: timeStamp property" — developer.mozilla.org
- MDN: "HTMLFormElement: submit event", "SubmitEvent: submitter property" — developer.mozilla.org
- DOM Living Standard: "Interface Event", "Dispatching events" — dom.spec.whatwg.org
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!