JavaScript

Mer om Events

Event Bubbling

HTML element kan ta emot olika events (händelser) som click, submit, mouseover, scroll m. fl.

 

Event bubbling är ett DOM-koncept och alla sådana HTML element följer per default konceptet event bubbling.

 

Exempel: Event Bubbling

# EVENT BUBBLING

Prova att klicka rosa fyrkanten, sen gröna, sen gula. Vad händer i konsolen?

Event Bubbling

Event Bubbling är alltså ett koncept hur DOM:en hanterar events per default.

 

När ett HTML element tar emot ett event, så "bubblar" det eventet uppåt i

DOM-trädet, ända tills det når root-elementet. Processen kallas event propagation, d.v.s händelsen "fortplantar" sig. Men just i detta fall bubblar händelsen uppåt.

 

Men innan eventet bubblar uppåt så sker en s.k event capturing. Något man inte märker av, men finns där.

Document

<html>

<body>

<div>

<div>

<div>

DOM-trädet 🌳

root-elementet

Capture phase

Document

<html>

<body>

<div>

<div>

<div>

DOM-trädet 🌳

root-elementet

Eventet "click" bubblar till nästa element

Bubble phase

Capture phase

Event Capture

motsatsen till event bubbling

Document

<html>

<body>

<div>

<div>

<div>

root-elementet

Eventet "click" bubblar till nästa föräldra element

Event Capture

Event Bubbling

eventet "fortplantar" sig från där det skedde till root-elementet

Event Bubbling och Capturing

motsatsen till event bubbling

Avbryta bubblandet?

Event bubbling är default för händelser i DOM.

 

Men det kan avbrytas med att använda stopPropagation()

 

Men man ska vara generellt försiktig att ändra default-beteenden, vilket lätt kan leda till buggar.

Exempel: Klicka en overlay för att stänga ner modalen

<!-- Overlay -->
<div id="overlay">
    <!-- Modal content -->
    <div id="modal">...</div>
</div>
# EVENT BUBBLING
const overlay = document.getElementById('overlay');
const modal = document.getElementById('modal');

overlay.addEventListener('click', function () {
    console.log('Close the modal');
});

modal.addEventListener('click', function (e) {
    e.stopPropagation();
});

Här används alltså stopPropagation() för att eventet i modalen inte ska bubbla vidare till overlayen. Men finns det annan lösning?

Exempel: Klicka en overlay för att stänga ner modalen

<!-- Overlay -->
<div id="overlay">
    <!-- Modal content -->
    <div id="modal">...</div>
</div>
# EVENT BUBBLING
const overlay = document.getElementById('overlay');
const modal = document.getElementById('modal');

overlay.addEventListener('click', function (event) {
    if (event.currentTarget === event.target) {
        console.log('Close the modal');
    }
});

Bättre att checka vilket event som ägt rum!

Event delegation

Baseras på konceptet Event bubbling.

 

Event delegation handlar om att hantera eventet på en högre nivå i DOM-trädet än där händelsen mottogs. D.v.s ett parent-element kan ta hand om händelsen som egentligen skedde på ett child-element

 

Idén är att man "delegerar" hanteringen av eventet till ett annan element.

Exempel: Lägga en händelselyssnare till varje childelement

<section>
  <button>Button 1</button>
  <button>Button 2</button>
  <button>Button 3</button>
</section>
# EVENT DELEGATION 
const buttons = document.querySelectorAll('button')

buttons.forEach(button => {
  button.addEventListener("click", (event) => {
    console.log(event.target.innerHTML)
  })
})

Det funkar att göra så här, men skulle det kunna optimeras med event delegation?

Exempel: Lägga en händelselyssnare på endast parent

<section>
  <button>Button 1</button>
  <button>Button 2</button>
  <button>Button 3</button>
</section>
# EVENT DELEGATION 
const parent = document.querySelector('section')

parent.addEventListener("click", (event) => {
  if(event.target.tagName === 'BUTTON') {
    console.log(event.target.innerHTML)
  }
})

Samma logik fast endast en lyssnare - bättre prestanda. Samt kan vi lägga till nya knappar utan problem!

Event-objektet

Text

Text

target = elementet där eventet ägde rum

preventDefault()

Defaultbeteendet för för ett HTML elements event-egenskaper genomförs inte.

 

Ex om preventDefault() sätts på en länk kommer inte webbläsaren följa länkarna.

 

Det är vanligt att använda vid <input type="submit"> som vanligtvis laddar om en sida. Om preventDefult() sätts på submit-eventet kommer sidan inte ladda om vid submit.

Tips på bra resurs