17 of 17 menu

Chyba duplikování funkce pro editaci DOM prvků v JavaScriptu

Předpokládejme, že máme nějaký seznam:

<ul> <li>1</li> <li>2</li> <li>3</li> </ul>

Získáme samotný seznam a jeho položky do samostatných proměnných:

let ul = document.querySelector('ul'); let lis = document.querySelectorAll('li');

Zařídíme, aby položky našeho seznamu šlo editovat pomocí zobrazeného inputu:

for (let li of lis) { li.addEventListener('click', function func() { let input = document.createElement('input'); input.value = list.textContent; li.textContent = ''; li.append(input); input.addEventListener('blur', function() { li.textContent = this.value; li.addEventListener('click', func); }); li.removeEventListener('click', func); }); }

Předpokládejme nyní, že chceme, aby do seznamu šlo přidávat nové položky. Pro tento účel mějme pod seznamem odpovídající input:

<input id="adder">

Získáme odkaz na tento input do proměnné:

let adder = document.querySelector('#adder');

Zařídíme, aby po ztrátě focusu inputu byla do seznamu přidána nová položka s textem převzatým z našeho inputu:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; ul.append(li); });

Předpokládejme nyní, že chceme, aby i nově přidané položky bylo také možné editovat. Samy od sebe pro ně editování fungovat nebude, protože když jsme zavěšovali obslužnou funkci kliknutí na položky seznamu, tyto položky ještě neexistovaly.

Podívejme se na možné varianty řešení tohoto problému.

První řešení

Nejjednodušší řešení - zduplikovat kód funkce func, připojit ji i pro nově vytvořené položky:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; li.addEventListener('click', function func() { // zde duplikujeme kód }); ul.append(li); });

Samozřejmě v tomto řešení hned vidíme nedostatek - duplikovat kód není správně.

Druhé řešení

Pro vyřešení problému duplikování je logické vyjmout funkci func ven, vytvořit z ní Function Declaration:

function func() { let input = document.createElement('input'); input.value = list.textContent; li.textContent = ''; li.append(input); input.addEventListener('blur', function() { li.textContent = this.value; li.addEventListener('click', func); }); li.removeEventListener('click', func); }

Zde na nás čeká problém. Jde o to, že naše funkce používala proměnnou li, získanou z vnější oblasti viditelnosti. Ale po vyjmutí funkce tato proměnná nyní není vidět!

Pro vyřešení problému budeme předávat naši li parametrem:

function func(li) { let input = document.createElement('input'); input.value = list.textContent; li.textContent = ''; li.append(input); input.addEventListener('blur', function() { li.textContent = this.value; li.addEventListener('click', func); }); li.removeEventListener('click', func); }

A zde naše řešení vytváří ještě jeden problém. Jde o to, že nejde jen tak předat parametr obslužné funkci události:

for (let li in lis) { li.addEventListener('click', func(li)); // nefunguje! }

Pro vyřešení tohoto problému jednoduše zavoláme naši funkci uvnitř anonymní obslužné funkce:

for (let li of lis) { li.addEventListener('click', function() { func(li); }); }

A obdobně postupujme při vytváření nové položky seznamu:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; li.addEventListener('click', function() { func(li); }); ul.append(li); });

Třetí řešení

Existuje elegantnější řešení. Lze jednoduše využít delegování událostí. V tomto případě problém s novými položkami seznamu jednoduše nevznikne:

ul.addEventListener('click', function(event) { if (event.target.tagName === 'LI') { // zachytáváme právě klik na li, ne na input let li = event.target; let input = document.createElement('input'); input.value = li.textContent; li.textContent = ''; li.append(input); input.addEventListener('blur', function() { li.textContent = this.value; }); } });

V tomto případě cyklus po položkách seznamu vůbec nebude potřeba a kód pro vytvoření nové položky seznamu se zkrátí na toto:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; ul.append(li); });
Čeština
AfrikaansAzərbaycanБългарскиবাংলাБеларускаяDanskDeutschΕλληνικάEnglishEspañolEestiSuomiFrançaisहिन्दीMagyarՀայերենIndonesiaItaliano日本語ქართულიҚазақ한국어КыргызчаLietuviųLatviešuМакедонскиMelayuမြန်မာNederlandsNorskPolskiPortuguêsRomânăРусскийසිංහලSlovenčinaSlovenščinaShqipСрпскиSrpskiSvenskaKiswahiliТоҷикӣไทยTürkmenTürkçeЎзбекOʻzbekTiếng Việt
Používáme soubory cookie pro fungování webu, analýzu a personalizaci. Zpracování údajů probíhá v souladu s Zásadami ochrany osobních údajů.
přijmout vše přizpůsobit odmítnout