Gabim i dyfishimit të funksionit të redaktimit të elementeve DOM në JavaScript
Le të themi se kemi një listë:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
Le të marrim vetë listën dhe pikat e saj në variabla të veçanta:
let ul = document.querySelector('ul');
let lis = document.querySelectorAll('li');
Le të bëjmë që pikat e listës sonë të mund të redaktohen me një input që shfaqet:
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);
});
}
Le të themi tani që duam që në listë të mund të shtohen pika të reja. Le të themi se për këtë nën listë do të kemi një input përkatës:
<input id="adder">
Le ta marrim lidhjen për këtë input në një variabël:
let adder = document.querySelector('#adder');
Le të bëjmë që pas humbjes së fokusit të input-it në listë të shtohet një pikë e re me tekst e marrë nga input-i ynë:
adder.addEventListener('blur', function() {
let li = document.createElement('li');
li.textContent = this.value;
ul.append(li);
});
Le të themi tani që duam që edhe pikat e shtuara rishtaz të mund të redaktohen. Në vetvete redaktimi për to nuk do të funksionojë, sepse kur ne i lidhëm përgjigjësin e klikimit në pikat e listës, këto pika nuk ekzistonin akoma.
Le të shohim variantet e mundshme për zgjidhjen e këtij problemi.
Zgjidhja e parë
Zgjidhja më e thjeshtë - është të dyfishojmë
kodin e funksionit func, duke e lidhur atë
edhe për pikat e krijuara rishtaz:
adder.addEventListener('blur', function() {
let li = document.createElement('li');
li.textContent = this.value;
li.addEventListener('click', function func() {
// këtu ne dyfishojmë kodin
});
ul.append(li);
});
Sigurisht, në këtë zgjidhje ne menjëherë shohim disavantazhin - nuk është e drejtë të dyfishosh kod.
Zgjidhja e dytë
Për të zgjidhur problemin e dyfishimit
është logjike të nxjerrim funksionin func
jashtë, duke e bërë atë 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);
}
Këtu na pret problemi.
Çështja është se funksioni ynë përdorte
variablin li, të marrë
nga fushëveprimi i jashtëm.
Por pas nxjerrjes së funksionit ky
variabël tani nuk është i dukshëm!
Për të zgjidhur problemin do ta kalojmë
li tonë si parametër:
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);
}
Dhe këtu zgjidhja jonë krijon edhe një problem tjetër. Çështja është se nuk mund të kalosh thjesht një parametër në një përgjigjës të ngjarjes:
for (let li in lis) {
li.addEventListener('click', func(li)); // nuk funksionon!
}
Për të zgjidhur këtë problem thjesht thirrni funksionin tonë brenda një përgjigjësi anonim:
for (let li of lis) {
li.addEventListener('click', function() {
func(li);
});
}
Dhe në mënyrë të ngjashme veprojmë gjatë krijimit të një pike të re të listës:
adder.addEventListener('blur', function() {
let li = document.createElement('li');
li.textContent = this.value;
li.addEventListener('click', function() {
func(li);
});
ul.append(li);
});
Zgjidhja e tretë
Ekziston një zgjidhje më elegante. Mund të përdorni thjesht delegimin. Në këtë rast problemi me pikat e reja të listës thjesht nuk do të lindë:
ul.addEventListener('click', function(event) {
if (event.target.tagName === 'LI') { // kapim pikërisht klikimin në li, jo në 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;
});
}
});
Në këtë rast cikli për pikat e listës në përgjithësi nuk do të na duhet, dhe kodi për krijimin e një pike të re të listës do të zvogëlohet në këtë:
adder.addEventListener('blur', function() {
let li = document.createElement('li');
li.textContent = this.value;
ul.append(li);
});