Първи стъпки в JavaScript – Събития (events)

Достигаме и до шеста част от уводната поредица в JavaScript. Тук ще обърнем внимание на събитията (event-и). Благодарение на събитията можем да изпълним код в ключов момент. Той може да е когато потребител извърши нещо конкретно. Може да бъде и когато друг обект извести, че е „готов“ с дадена функционалност

Event-ите могат да се използват за интеракция и повече динамика в страниците. Благодарение на тях можем да извършим някаква инициализация, когато страницата е заредена.

Event-ите в JavaScript са едно от най-важните и често използваните неща в езика.

Един от най-лесните, но неправилни начини е със следния синтаксис:

function doSomething() {
	// тяло на функцията
}

window.onload = doSomething;

Първо дефинираме функцията doSomething(). След това я присвояваме на onload property-то на обекта window. При пълното зареждане на страницата обектът window хвърля load event. Той кара самият обект да изпълни своето property onload в случай, че то е функция.

Проблемът в този подход е, че можем да изпълним една единствена функция при зареждането на страницата.

addEventListener

По-правилен начин, който позволява да асоциирате няколко handler функции при един и същи event е следния:

function doSomething() {
	// тяло на функцията
}

function doSomethingElse() {
	// тяло на втората функция
}

window.addEventListener('load', doSomething, true);
window.addEventListener('load', doSomethingElse, true); 

Самият метод addEventListener() приема три аргумента:

  1. type – тип на събитието
  2. listener – функция, която да се изпълни
  3. useCapture – булева стойност (true/false), която по подразбиране е false.

Фази на събитията

Capture

Capture е фазата от събитието, при която се влиза навътре към елементите.

Нека разгледаме елементите като кутии, в които можем да имаме други такива.

Следната структура:

<div>
	<ul>
		<li>
			<a href="#">Click</a>
		</li>
	</ul>
</div>

може да се оприличи на 4 матрьошки.

Ако се опитаме да кликнем на линка най-вътре, първо трябва мишката да „мине“ през по-външните елементи. Даже първо ще мине през най-външния.

Ако useCapture е true, функцията ще се изпълни още при click на div-а, след това на ul, после на li и накрая на a.

Bubble

След като стигнем до най-вътрешния елемент, започва bubble фазата. Нарича се така, защото върви наобратно – от най-вътрешния към най-външния елемент.

По подразбиране събитията се изпълняват в този ред. И ако имаме клик на линка ще можем първо да обработим него. Чак след това ще дойде li, после ul и накрая div.

Обект на събитието

Функциите, които се изпълняват при събитие, автоматично получават аргумент обекта на събитието. Този обект съдържа информация за:

  • типа на събитието
  • кой е най-вътрешният елемент, който го е предизвикал
  • кой е текущият елемент, на който всъщност сме задали handler-а
  • множество друга информация, в зависимост от това какво е точно събитието, което обработваме.
function eventInfo(e) {
	alert('target: ' + e.target.nodeName);
	alert('currentTarget: ' + e.currentTarget.nodeName);
}

document.getElementById('div').addEventListener('click', eventInfo);
document.getElementById('a').addEventListener('click', eventInfo);

В този пример декларираме функцията eventInfo().

Тя приема аргумент e. Това е съкратено от event. Аргументът във функцията можем да наименоваме различно. Аз лично съм свикнал винаги да ползвам e (като конвенция).

target и currentTarget

Функцията показва 2 съобщения. Първото дава информация за target обекта на събитието.

target е най-вътрешният елемент, който е предизвикал събитието. При click събития, това е елементът, който реално сме кликнали.

Във второто съобщение показваме currentTarget обекта. Това е обектът, към който сме задали event listener.

В единия случай от примера и двете съобщения ще се отнасят за link-а. В другия обаче ще върнем информация за link-а като target, а после и div-а като currentTarget. Това, защото сме задали addEventListener на div-а (затова currentTarget).

Чрез document.getElementById(id) достъпваме елемент от страницата, която сме заредили. Като аргумент на функцията подаваме string с ID-то на елемента, който искаме да селектираме. В случая се предполага, че имаме div с id="div" и a с id="a". При клик и на двата елемента извикваме една и съща функция – eventInfo().

В случая не използваме useCapture, което означава, че listener-ите ще се изпълнят първо за А-тага, а след това за DIV-а.

target-а на A-тагът е самият A таг, затова e.target.nodeName има стойност A.

currentTarget обектът на събитието е същият елемент, тъй като event listener-ът е зададен за този таг.

След като събитието е обработено то продължава към parent елемента (DIV-ът) през своята bubble фаза.

На нов ред се извиква функцията. target елементът е A-тагът, но този път вече currentTarget е DIV-ът.

Резултат: popup-и със следните надписи:

  • target: A
  • currentTarget: A
  • target: A
  • currentTarget: DIV

Ако бяхме задали useCapture = true за двата event listener-а (всъщност е достатъчно и само за DIV-ът), тогава първо щеше да се изпълни неговият event listener, но target-а щеше да си остане А-то. Резултатът щяха да са popup-и със следните надписи:

  • target: A
  • currentTarget: DIV
  • target: A
  • currentTarget: A

Вашият коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *

Този сайт използва Akismet за намаляване на спама. Научете как се обработват данните ви за коментари.