Přidávání obslužných rutin k novým prvkům v JavaScriptu

Předpokládejme, že máme seznam ul a tlačítko:

html<ul>
  <li>položka</li>
  <li>položka</li>
  <li>položka</li>
  <li>položka</li>
  <li>položka</li>
</ul>

<button>přidat</button>

Získáme naše prvky do odpovídajících proměnných:

javascriptlet button = document.querySelector('button');
let list   = document.querySelector('ul');
let items  = list.querySelectorAll('li');

Zařídíme, aby po kliknutí na jakoukoli li se na její konec přidal vykřičník:

javascriptfor (let item of items) {
  item.addEventListener('click', function() {
    this.textContent = this.textContent + '!';
  });
}

Nyní udělejme to, aby po stisknutí tlačítka se na konec seznamu přidala nová li:

javascriptbutton.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'položka';
  list.appendChild(item);
});

Dostaneme však problém: kliknutí na nově přidanou li nepovede k přidání vykřičníku na konec. Jde o to, že přidáváme obslužnou rutinu kliknutí pouze na ty li, které existovaly původně, ale ne na nové.

Problém opravíme přidáním obslužné rutiny kliknutí na novou li:

javascriptbutton.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'položka';
  
  item.addEventListener('click', function() { // obslužná rutina kliknutí
    this.textContent = this.textContent + '!';
  });
  
  list.appendChild(item);
});

Nyní se však kód funkce-obslužné rutiny duplikuje na dvou místech - pro původně existující li a pro nové. Opravme to jejím vyjmutím do samostatné funkce:

javascriptfunction handler() {
  this.textContent = this.textContent + '!';
}

Použijeme naši funkci, abychom se vyhnuli duplikování kódu:

javascriptfor (let item of items) {
  item.addEventListener('click', handler);
}

button.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'položka';
  
  item.addEventListener('click', handler);
  
  list.appendChild(item);
});

Úloha je v podstatě vyřešena a vyhnuli jsme se duplikování kódu funkce-obslužné rutiny. Nicméně, přidávat obslužné rutiny událostí nám stále musíme na dvou místech: jak ve smyčce pro existující li, tak při kliknutí na tlačítko. V následující lekci si rozebereme způsob, jak se tohoto nepohodlí zbavit.