ივენთები

ბრაუზერში მრავალი მოვლენა ხდება. ზოგს თვითონ ბრაუზერი აწარმოებს - მაგალითად როცა კონტენტს ტვირთავს - ხოლო ზოგიერთს მომხმარებელი იწვევს: მაგალითად მაუსზე დაკლიკება, ფორმის ველებში ტექსტის შეყვანა და ა.შ. DOM საშუალებას გვაძლევს, რომ დოკუმენტში ასეთ მოვლენებს მოვუსმინოთ და მათზე ვირეაგიროთ.

ივენთზე მოსმენა

როცა მომხმარებელი რაიმე მოვლენას შეასრულებს, მაგალითად მაუსით დააკლიკებს კონკრეტულ ელემენტზე, ბრაუზერი ამ ელემენტზე გასცემს click მოვლენას, რომელსაც ჩვენ შეგვიძლია წინასწარ მოვუსმინოთ. მოსმენის ლოგიკა ძირითადად 3 ნაწილისგან შედგება:

  • ელემენტის მოხელთება
  • ელემენტზე "მოვლენის მომსმენის" (event listener) დაყენება
  • "მოვლენის მომსმენში" იმ ლოგიკის განსაზღვრა, რომელიც საპასუხოდ უნდა მოხდეს.

მაგალითისთვის შევქმნათ HTML-ში ღილაკი:

HTML
<button>შეტყობინების გამოტანა</button>

ახლა კი საჭიროა მას დავუმატოთ მოვლენის მომსმენი. ამის შესრულება შეიძლება სამნაირად:

  • პირდაპირ HTML-შივე გავუწერთო ივენთის მომსმენი.
  • JavaScript-ს მხარეს უკვე ამოღებულ ელემენტზე გავწეროთ addEventListener.

პირდაპირ HTML-ში ჩვენ შეგვიძლია ელემენტს მივანიჭოთ onclick ატრიბუტი რომლის მნიშვნელობაც იქნება ფუნქციაზე დაძახება. აუცილებელია, რომ დოკუმენტში რომელიმე სკრიპტში განსაზღვრული იყოს ეს ფუნქცია.

HTML
<button onclick="logText()">შეტყობინების დალოგვა</button>
JS
function logText() {
  console.log('ღილაკზე დაეკლიკა');
}

ალტერნატიული ვარიანტია ელემენტის ამოღება ჯავასკრიპტში და მასზე addEventListener მეთოდის დაძახება.

JS
button.addEventListener('click', logText);

function logText() {
  console.log('ღილაკზე დაეკლიკა');
}

ორივე მიდგომა დალოგავს ტექსტს 'ღილაკზე დაეკლიკა', თუმცა ჩნდება კითხვა: რომელი არის ყველაზე ეფექტური მიდგომა? ორივე მიდგომის შედეგი კი იგივე არის, მაგრამ უფრო მოსახერხებელი არის addEventListener. HTML-ის ატრიბუტებში არ არსებობს ყველა ის მოვლენა, რომელიც ელემენტზე ხდება. addEventListener-ის გამოყენებით შესაძლებელია ნებისმიერი მოვლენის მოხელთება და დამატებითი პარამეტრების გადაცემა, მისი შედარებით უფრო დინამიურად გამოყენება და დაკავშირებული ივენთის მოხსნაც, რომელიც იმავე პრინციპით ხდება, როგორც დამატება.

პარამეტრი

თითოეულ ივენთის მომსმენს სჭირდება ფუნქცია რომელსაც ამ მოვლენის დროს დაუძახებს. ამ ფუნქციაში ყოველთვის შეგვიძლია განვსაზღვროთ ერთი პარამეტრი. ეს პარამეტრი არის Event ტიპის ობიექტი, სადაც ბევრი კარგი მეთოდი და თვისება არის ჩაშენებული.

HTML
<button>ივენთის გამოძახება</button>
JS
const button = document.querySelector('button');

button.addEventListener('click', function (event) {
  console.log(event, this);
});

button.addEventListener('click', (event) => {
  console.log(event, this);
});

ამ შემთხვევაში ამოვიღეთ HTML-დან პირველი button და მასზე დავამატეთ ორი ივენთის მომსმენი, ორივეგან გავაყოლეთ პარამეტრში event, რომელიც სურვილისამებრ შეიძლება ავღწეროთ ისივე, როგორც მასივის callback ფუნქციებში ხდება. ორივე ფუნქცია დალოგავს event პარამეტრს და ასევე this ობიექტს. this ორივე შემთხვევაში განსხვავებული იქნება, წინა სტატიებში (რა არის This ?) განვიხილეთ this განსხვავება ჩვეულებრივ და arrow ფუნქციებში. ჩვეულებრივი ფუნქციის (function) this არის ლოკალური კონტექსტის მატარებელი. ის გვიბრუნებს იმ ობიექტს, რომელზეც მოხდა ფუნქციის გამოძახება - ჩვენს შემთხვევაში button, ხოლო arrow ფუნქციაში this წარმოადგენს გლობალური კონტექტის მნიშვნელობას.

arrow ფუნქცია ჯობია გამოიყენოთ მაშინ, როცა გსურთ უბრალოდ callback ფუნქციის აღწერა და არ გჭირდება this გამოყენება, ხოლო ჩვეულებრივი ფუნქცია ჯობია მაშინ გამოიყენოთ, როცა გჭირდებათ this.

ივენთის მოსმენის გათიშვა

წინა მაგალითებში რამდენჯერაც დავწერეთ addEventListener იმდენჯერ დავაკავშირეთ რაღაც ფუნქცია დაკლიკებასთან. დაკლიკების შემთხვევაში ყოველ ჯერზე მიწოდებული ფუნქცია გაეშვება. ზოგჯერ გვჭირდება არსებულ ელემენტებზე ივენთის მოსმენის გათიშვა, ამისათვის კი გამოიყენება removeEventListener. ასევე, შეგვიძლია addEventListener options პარამეტრებში გავატანოთ { once: true }, რისი შედეგადაც ჩვენი ივენთი მხოლოდ ერთხელ მოისმინება და შემდგომ მოხდება ივენთის მოსმენის გათიშვა. თუ ვიცით რომ რაღაც დროის შემდგომ ელემენტზე ივენთის მოსმენა უნდა შევწყვიტოთ მაშინ აუცილებელია callback ფუნქცია აღვწეროთ ცალკე ცვლადში

განვიხილოთ ივენთის მოსმენის გათიშვის მაგალითი:

HTML
<button id="logBtn">ლოგში შეტყობინების გამოტანა</button>
<button id="removeListenerBtn">პირველი ღილაკის ივენთის მომსმენის გათიშვა</button>
JS
const logBtn = document.querySelector('#logBtn');
const removeListenerBtn = document.querySelector('#removeListenerBtn');

logBtn.addEventListener('click', handleClick);

removeListenerBtn.addEventListener('click', () => {
  console.log('გაითიშა დამლოგავი ღილაკის ივენთის მოსმენა');
  logBtn.removeEventListener('click', handleClick);
});

function handleClick() {
  console.log('რაღაც საინტერესო ტექსტი');
}

მაგალითიდან ჩანს, რომ სანამ მეორე ღილაკს დავაწვებით, მანამდე პირველი ღილაკი ლოგავს ტექსტს, მაგრამ როგორც კი მეორე ღილაკს დავაკლიკებთ მისი ივენთის მოსმენა ითიშება. removeEventListener იგივე ნაირად ღებულბოს პარამეტრებს, როგორც addEventListener.

ივენთების ჩამონათვალი

JavaScript-ში საკმაოდ ბევრი კარგი ჩაშენებული ივენთი არის. ცხრილში მოცემულია მათი (არასრული) ჩამონათვალი:

ივენთის სახელი ივენთის ფუნქციის სახელი ივენთის ტიპი აღწერა
abort onabort Event გაეშვება მაშინ როცა რესურსი/სკრიპტი სრულიად ჩატვირთული არ არის მაგრამ არც ერორი არ გვაქვს
animationend onanimationend AnimationEvent გაეშვება მაშინ როცა CSS ანიმაცია შესრულდება
animationiteration onanimationiteration AnimationEvent გაეშვება მაშინ როცა CSS ანიმაცია თავიდან დაიწყებს იტერაციას (გაშვებას)
animationstart onanimationstart AnimationEvent გაეშვება მაშინ როცა CSS ანიმაცია დაიწყება
auxclick onauxclick PointerEvent გაეშვება მაშინ როცა არამთავარ (სქროლის ან მარჯვენა) მაუსის ღილაკზე მოხდება დაკლიეკბა
blur onblur FocusEvent გაეშვება მაშინ როცა ელემენტი დაკარგავს ფოკუს
change onchange Event გაეშვება მაშინ <input>, <select> ან ტეხტარეა შეიცვლის მნიშვნელობას და ელემენტი დაკარგავს ფოკუს ან როცა მომხარებელი შეცვლის მნიშვნელობას
click onclick PointerEvent გაეშვება მაშინ როცა ელემენტზე მოხდება დაკლიკება
contextmenu oncontextmenu PointerEvent გაეშვება მაშინ როცა მაუსის მარჯვენა ღილაკით მოხდება დაკლიკება (კონტექსტური მენიუსთვის განკუთვნილი ღილაკით)
copy oncopy ClipboardEvent გაშვება მაშინ როცა მომხარებელი აკოპირებს ტექსტს ელემენტიდან
dblclick ondblclick MouseEvent გაეშვება მაშინ როცა მოხდება ელემენტზე ორჯერ დაკლიკება
drag ondrag DragEvent გაეშვება მაშინ როცა ელემენტის გადაადგილება დაიწყო
dragend ondragend DragEvent გაეშვება მაშინ როცა გადაადგილების ოპერაცია დასრულდა (მაგალთად: მომხარებელმა მაუს ხელი აუშვა ან დააჭირა ესქეიპ ღილაკს) დაიწყო
dragenter ondragenter DragEvent გაეშვება მაშინ როცა ელემენტი ან არჩეული ტექსტი შედის ვალიდურ გადაადგილების არეალში
dragleave ondragleave DragEvent გაეშვება მაშინ როცა ელემენტი ან არჩეული ტექსტი გამოდის ვალიდური გადაადგილების არეალიდან
dragover ondragover DragEvent გაეშვება მაშინ როცა ელემენტი დაიტოვება ვალიდურ გადასაადგილებელ ადგილას
dragstart ondragstart DragEvent გაეშვება მაშინ როცა ელემენტის გადაადგილების ოპერაცია დაიწყო (ელემენტის ან ტექსტის გადაადგილებით)
drop ondrop DragEvent გაეშება მაშინ როცა ელემენტი გადაადგილების დროს დავტოვებთ ვალიდურ ადგილას
focus onfocus FocusEvent გაეშვება მაშინ როცა ელემენტი ფოკუსის არეალში მოექცევა
focusin არ აქვს FocusEvent გაეშვება მაშინ როცა ელემენტმა ესესაა უნდა მიღოს ფოკუსი
focusout არ აქვს FocusEvent გაეშვება მაშინ როცა ელემენტმა ესესაა უნდა დაკარგოს ფოკუსი
input oninput InputEvent გაეშვება სინქრონულად როცა ელემენტის მნიშვნელობა იცვლება (<input>, <select> ან <textarea>)
keydown onkeydown KeyboardEvent გაეშვება მაშინ როცა კლავიშზე მოხდა დაკლიკება (ეს მეთოდი არის keypress გაუმჯობესებული ვერსია, keypress-ს გამოყენება აღარ არის პრაქტიკაში მიღებული, გამოცხადებულია როგორც Deprecated)
keyup onkeyup KeyboardEvent გაეშვება მაშინ როცა კლავიშიდან ხელს ავიღებთ (აღარ ხდება დაჭერა)
load onload Event გაეშვება მაშინ როცა მთლიანი გვერდი ჩაიტვირთება, იგულისხმება ყოველი დამოკიდებული რესურსი (სტილები, სკრიპტები, სურათები, iframe)
mousedown onmousedown MouseEvent გაეშვება მაშინ როცა მაუსის ღილაკზე დაკლიკებულია
mouseup onmouseup MouseEvent გაეშვება მაშინ როცა მაუსის ღილაკზე დაკლიკება შეწყდება
mouseenter onmouseenter MouseEvent გაეშვება მაშინ როცა მოხდება ელემენტზე მაუსის გადატარება ხილვად არეალზე (:hover მსგავსად)
mouseleave onmouseleave MouseEvent გაეშვება მაშინ როცა მაუსი დატოვებს ელემენტის ხილვად არეალს (:hover საპირისპიროდ)
mousemove onmousemove MouseEvent გაეშვება მაშინ როცა მოხდება ელემენტის შიგნით მაუსის გამოძრავება
mouseout onmouseout MouseEvent გაეშვება მაშინ როცა მაუსი დატოვებს ელემენტს
mouseover onmouseover MouseEvent გაეშვება მაშინ როცა მოხდება მაუსის გადატარება ელემენტზე ან მის შვილობილ ელემენტებზე
paste onpaste ClipboardEvent გაეშვება მაშინ როცა მოხდება კონტენტის ჩასმა ელემენტში (paste)
reset onreset Event გაეშვება მაშინ როცა მოხდება ფორმის დარესეტება (ყველაფრის ნაგულისხმევ მნიშვნელობაზე დაბრუნება)
resize onresize Event გაეშვება მაშინ როცა მოხდება window ზომის ცვლილება
scroll onscroll Event გაეშვება მაშინ როდესაც მოხდება სქროლი (ზემოთ ასვლა ან ქვემოთ ჩამოსვლა)
select onselect Event გაეშვება მაშინ როცა მოხდება ტექსტი ინიშნება
submit onsubmit SubmitEvent გაეშვება მაშინ როცა მოხდება ფორმის დადასტურება (დასრულება)
transitionend ontransitionend TransitionEvent გაეშვება მაშინ როცა მორჩება CSS transition
wheel onwheel WheelEvent გაეშვება მაშინ როცა მომხარებელი დაატრიალებს მაუსის შუა ღილაკს (წააგავს scroll ივენთს თუმცა გააჩნია განსხვავებები დელტა თვისების ცვილებებში და სხვა თვისებებშიც)

შეჯამება

JavaScript-ს გააჩნია ბევრი ჩაშენებული ივენთი სხვადასხვა სიტუაციებისთვის. იმისათვის, რომ რომელიმე ელემენტზე რაიმე ივენთს მოვუსმინოთ საჭიროა ჯერ ამ ელემენტის ამოღება და შემდგომ მასზე ივენთის მიბმა, თუ ვაპირებთ რაღაც პერიოდის მერე ივენთის მოსმენის გაუქმებას, საჭიროა ცალკე ფუნქციაში ავღწეროთ და არ გადავცეთ პირდაპირ, როგორც callback ფუნქცია. ხშირ შემთხვევაში ჯობია addEventListener გამოყენება ვიდრე HTML-ში ატრიბუტების გაწერა, რადგან იგი უფრო მეტ მოქნილობას გვთავაზობს.

იხილეთ სამაგალითო კოდები playground-ში.