Hodisalarga kirish

Brauzer hodisalariga kirish

Hodisa (event) โ€” bu biror voqea sodir bo'lgani haqidagi "signal". Barcha DOM tugunlari bunday signallarni yuboradi (garchi hodisalar faqat DOM bilan cheklanmasa ham). Ushbu darsda hodisalarning umumiy tamoyillari va ularga qanday ishlov berishni chuqur o'rganamiz.

Hodisa nima?

Foydalanuvchi sahifa bilan o'zaro aloqada bo'lganda yoki brauzer ichida biror voqea yuz berganda hodisa ishga tushadi (fire/trigger). Eng ko'p uchraydigan DOM hodisalarining ba'zilari:

Sichqoncha hodisalari:

Klaviatura hodisalari:

Forma elementi hodisalari:

Hujjat hodisalari:

CSS hodisalari:

Bu ro'yxat to'liq emas โ€” hodisalar juda ko'p. Hozircha eng muhimi shuni tushunish: har qanday voqeaga ishlovchi (handler) โ€” ya'ni hodisa sodir bo'lganda ishga tushadigan funksiya biriktirish mumkin.

Ishlovchi (handler) nima?

Hodisalarga ishlov berish uchun ishlovchi โ€” hodisa sodir bo'lganda ishlaydigan funksiya biriktiramiz. Ishlovchilar foydalanuvchi harakatiga JavaScript kodi bilan javob berishning asosiy usulidir. Ishlovchini biriktirishning bir necha yo'li bor. Ularni oddiydan murakkabga qarab ko'rib chiqamiz.

1-usul: HTML atributi (onclick)

Ishlovchini to'g'ridan-to'g'ri HTML ichida on<hodisa> ko'rinishidagi atribut bilan berish mumkin. Masalan, click hodisasi uchun onclick atributini yozamiz:

<input value="Bosing!" onclick="alert('Salom!')" type="button">

Sichqoncha bosilganda onclick ichidagi kod ishga tushadi. Atribut ichiga to'g'ridan-to'g'ri kod yozilganiga e'tibor bering โ€” bu yerda alert('Salom!') chaqiriladi.

HTML atributi ichida ikki tirnoq ishlatib bo'lmaydi, chunki atribut o'zi ikki tirnoq bilan o'ralgan: onclick="...". Shu sabab ichida bitta tirnoq ishlatiladi: onclick="alert('Salom!')". Agar ikki tirnoq zarur bo'lsa, &quot; HTML-entitisidan foydalaniladi.

Kod uzun bo'lsa, uni funksiyaga o'rab, atributdan chaqirish maqsadga muvofiq:

<script>
  function countRabbits() {
    for (let i = 1; i <= 3; i++) {
      alert('Quyoncha raqami ' + i);
    }
  }
</script>

<input type="button" onclick="countRabbits()" value="Quyonchalarni sana!">
HTML atributlari harf katta-kichikligiga sezgir emas, shuning uchun ONCLICK ham, onClick ham, onclick ham ishlaydi. Lekin odatda atributlar kichik harflar bilan yoziladi: onclick.
HTML atributi orqali ishlov berish qulay ko'rinsa-da, kamdan-kam ishlatiladi. Sababi: HTML va JavaScript aralashib ketadi, kod uzun bo'lsa o'qib bo'lmaydigan holga keladi. Odatda ishlovchilar JavaScript ichida biriktiriladi.

2-usul: DOM xossasi (elem.onclick)

Ishlovchini DOM xossasi on<hodisa> orqali ham biriktirish mumkin. Masalan, elem.onclickga funksiya tayinlaymiz:

<input id="elem" type="button" value="Bosing!">

<script>
  elem.onclick = function() {
    alert('Rahmat');
  };
</script>

Endi element bosilsa, funksiya ishga tushadi. Diqqat: ishlovchi elem.onclick = ... ko'rinishida tayinlanadi, chaqirilmaydi. Ya'ni funksiyaning o'zini beramiz (nomidan keyin qavs qo'ymaymiz), uni brauzerning o'zi kerakli paytda chaqiradi.

Agar ishlovchi HTML atributi orqali berilsa, brauzer atribut mazmunidan avtomatik funksiya yaratib, uni elem.onclickga tayinlaydi. Ya'ni bu ikki usul aslida bir xil natijaga olib keladi.

onclick faqat bitta bo'la oladi

DOM xossasi orqali biriktirilganda faqat bitta ishlovchi bo'lishi mumkin. Yangi ishlovchi tayinlansa, u eskisini o'chirib tashlaydi (ustidan yozadi):

elem.onclick = function() { alert(1); };
// ...
elem.onclick = function() { alert(2); }; // eski ishlovchi almashtiriladi
// endi faqat 2 ko'rsatiladi

Ishlovchini olib tashlash uchun elem.onclick = null qilamiz.

Ishlovchini tashqarida e'lon qilingan nomli funksiyaga ham tayinlash mumkin: elem.onclick = sayThanks;. Bu yerda ham funksiya nomidan keyin qavs qo'yilmaydi โ€” aks holda (sayThanks()) funksiyaning natijasi tayinlanadi, funksiyaning o'zi emas.

3-usul: addEventListener

HTML atributi va DOM xossasining asosiy kamchiligi โ€” bitta hodisaga bir nechta ishlovchi biriktirib bo'lmasligi. Masalan, bir kod tugma bosilganda reklamani yoritmoqchi, boshqasi esa xabar chiqarmoqchi bo'lsa, ikkovi ham kerak. Lekin yangi onclick eskisini o'chiradi.

Shu muammoni hal qilish uchun maxsus addEventListener va removeEventListener metodlari mavjud. Ular DOM xossasining cheklovlaridan xoli va zamonaviy amaliyotda afzal ko'riladi.

Sintaksis:

element.addEventListener(event, handler, options);
elem.addEventListener('click', function() {
  alert('Rahmat!');
});

Ishlovchini olib tashlash uchun removeEventListener ishlatamiz:

element.removeEventListener(event, handler, options);
Ishlovchini olib tashlash uchun aynan o'sha funksiya uzatilishi kerak. Anonim (nomsiz) funksiya tayinlangan bo'lsa, uni o'chirib bo'lmaydi:
// bunday qilib bo'lmaydi โ€” o'chirish uchun funksiyaga havola yo'q:
elem.addEventListener('click', () => alert('Rahmat!'));
// ...
elem.removeEventListener('click', () => alert('Rahmat!')); // ISHLAMAYDI
// (bu boshqa funksiya, garchi kodi bir xil bo'lsa ham)

To'g'ri yo'l โ€” funksiyani o'zgaruvchida saqlab, o'sha havolani uzatish:

function handler() {
  alert('Rahmat!');
}

elem.addEventListener('click', handler);
// ...
elem.removeEventListener('click', handler); // endi ishlaydi

Bir nechta ishlovchi

addEventListenerning asosiy kuchi โ€” bir hodisaga ko'p ishlovchi biriktirish imkoni:

<input id="elem" type="button" value="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 bosish natijasida uchala ishlovchi ham ishga tushadi: onclick orqali biriktirilgani va addEventListener orqali biriktirilgan ikkitasi. Ya'ni onclick va addEventListener bir-biriga xalaqit bermaydi.

Ba'zi hodisalarni faqat addEventListener orqali biriktirish mumkin, DOM xossasi orqali emas. Masalan, DOMContentLoaded hodisasi (hujjat yuklanib, DOM tayyor bo'lganda ishga tushadi). Uning document.onDOMContentLoaded degan xossasi yo'q โ€” faqat document.addEventListener('DOMContentLoaded', ...) ishlaydi.

Hodisa obyekti (event object)

Hodisani to'g'ri qayta ishlash uchun ko'pincha nima sodir bo'lgani haqida ko'proq ma'lumot kerak: qaysi tugma bosildi, sichqoncha koordinatalari qanaqa va hokazo. Hodisa sodir bo'lganda brauzer hodisa obyektini (event object) yaratib, uni ishlovchiga birinchi argument sifatida uzatadi.

<input type="button" value="Meni bosing" id="elem">

<script>
  elem.onclick = function(event) {
    // hodisa turini va elementni ko'rsatamiz
    alert(event.type + ' element ' + event.currentTarget);
    // sichqoncha koordinatalari
    alert(event.clientX + ':' + event.clientY);
  };
</script>

Hodisa obyektining eng ko'p ishlatiladigan xossalari:

Hodisa obyektining boshqa ko'plab xossalari ham bor va ular hodisa turiga bog'liq. Masalan, klaviatura hodisalarida bosilgan tugma haqida ma'lumot, sichqoncha hodisalarida koordinatalar bo'ladi. Ularni keyinroq maxsus darslarda o'rganamiz. Hozircha muhimi: ishlovchi birinchi argument sifatida hodisa obyektini oladi.
HTML atribut orqali berilgan ishlovchida ham hodisa obyekti event nomi bilan mavjud: <input onclick="alert(event.type)">. Brauzer atributdan funksiya yaratganda, uning birinchi argumentini event deb nomlaydi.

this ishlovchi ichida

Ishlovchi ichida this โ€” bu ishlovchi biriktirilgan elementga havola qiladi. Quyidagi misolda tugma bosilganda o'zining valuesi (matni) ko'rsatiladi:

<button onclick="alert(this.innerHTML)">Meni bosing</button>

Bu yerda this.innerHTML โ€” tugmaning ichidagi matn, ya'ni 'Meni bosing'. Xuddi shu narsa DOM xossasi va addEventListener orqali biriktirilgan oddiy funksiyalarda ham ishlaydi.

Strelka funksiyalarida (arrow functions) o'z thissi yo'q โ€” u tashqi ko'lamdan olinadi. Shuning uchun ishlovchida this orqali elementga murojaat qilmoqchi bo'lsangiz, strelka funksiya emas, oddiy funksiya ishlating. Strelka ishlatilsa, this element emas, tashqi (masalan, global) qiymat bo'ladi. Bunday holda event.currentTargetdan foydalaning.

Obyekt-ishlovchi va handleEvent

addEventListener ishlovchi sifatida nafaqat funksiya, balki obyekt ham qabul qila oladi. Hodisa sodir bo'lganda, obyektning handleEvent metodi chaqiriladi:

<button id="elem">Meni bosing</button>

<script>
  let obj = {
    handleEvent(event) {
      alert(event.type + ' element ustida ' + event.currentTarget.tagName);
    }
  };

  elem.addEventListener('click', obj);
</script>

Ya'ni addEventListener obyekt olsa, hodisa yuz berganda uning handleEvent(event) metodini chaqiradi. Bu metod istagancha ishlovni bajarishi mumkin.

handleEvent metodi obyektning o'zida bo'lishi shart emas โ€” uni klass orqali ham amalga oshirish mumkin. Bu bir nechta hodisani bitta obyektda boshqarish uchun qulay:

<button id="elem">Meni 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 bitta menu obyekti ikki xil hodisaga ishlov beradi. handleEvent ichida event.type orqali qaysi hodisa kelganini ajratamiz.

handleEvent metodi ishlovni to'liq o'zi bajarishi shart emas โ€” u faqat boshqa metodlarni chaqirishi ham mumkin. Bu hodisalarga obyektga yo'naltirilgan (OOP) usulda ishlov berish imkonini beradi.

Xulosa

Ishlovchi biriktirishning uch usuli: