Ukrywanie tekstu podczas edycji elementu w JavaScript

Teraz sprawmy, aby podczas edycji input pojawiał się bezpośrednio w akapicie - zamiast tekstu tego akapitu. Niech potem po zakończeniu edycji input zostanie usunięty, a zamiast niego znów pojawi się tekst akapitu.

Przystąpmy do realizacji.

Na początek zróbmy tak, aby po kliknięciu w akapit na jego końcu dodawany był input z tekstem tego akapitu:

javascriptlet elem = document.querySelector('#elem');

elem.addEventListener('click', function() {
  let input = document.createElement('input');
  input.value = elem.textContent;
  
  elem.appendChild(input);
});

Nasz kod jest jednak bardzo niedoskonały - za każdym razem po kliknięciu w akapit będzie do niego dodawany nowy input.

Przy tym, jeśli w pierwszym inpucie będzie znajdować się tekst akapitu, to w drugim inpucie będzie już znajdować się tekst akapitu razem z pierwszym inputem, a w trzecim inpucie będzie już znajdować się tekst akapitu razem z dwoma inputami i tak dalej.

Zwróć także uwagę na to, że kliknięcie dodanego inputu będzie interpretowane jako kliknięcie w akapit: chodzi o to, że input znajduje się w akapicie, i kliknięcie w input po prostu wypłynie (bubble) w górę do tego akapitu.

Doprowadzi to do tego, że po pojawieniu się pierwszego inputu przy próbie kliknięcia w niego po to, aby rozpocząć edycję, automatycznie zrobimy kliknięcie w akapit ze wszystkimi wynikającymi z tego konsekwencjami.

A zatem, problem został zarysowany. Teraz go naprawmy.

Aby to zrobić, po prostu przy pojawieniu się inputu odepnijmy od akapitu nasłuchiwacz zdarzenia kliknięcia. W tym przypadku tylko pierwsze kliknięcie w akapit będzie prowadzić do pojawienia się inputu, a pozostałe kliknięcia, wykonane po pojawieniu się inputu, zostaną zignorowane.

Zrealizujmy to:

javascriptlet elem = document.querySelector('#elem');

elem.addEventListener('click', function func() {
  let input = document.createElement('input');
  input.value = elem.textContent;
  
  elem.appendChild(input);
  
  elem.removeEventListener('click', func); // odpinamy zdarzenie
});

Zróbmy teraz tak, aby przy pojawieniu się inputu, tekst samego akapitu znikał. W tym celu przed wstawieniem inputu textContent akapitu przypiszmy pustemu stringowi:

javascriptlet elem = document.querySelector('#elem');

elem.addEventListener('click', function func() {
  let input = document.createElement('input');
  
  input.value = elem.textContent; // najpierw zapisujemy tekst akapitu w inpucie
  elem.textContent = ''; // następnie usuwamy tekst akapitu
  elem.appendChild(input); // następnie wstawiamy input
  
  elem.removeEventListener('click', func);
});

Zróbmy teraz tak, aby przy utracie fokusu w inpucie tekst tego inputu został zapisany w akapicie:

javascriptlet elem = document.querySelector('#elem');

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

Zwróć uwagę na to, że nie musimy usuwać inputu - usuwa się on sam, kiedy zapisuje swój tekst w akapicie: ponieważ input jest częścią tekstu akapitu, to zapis jakiegoś tekstu w ten akapit po prostu usuwa nasz input, i tyle.

Mamy jednak jeszcze jeden problem: tekst akapitu będzie edytowany tylko za pierwszym razem. Po pierwszej edycji ponowne naciśnięcie na tekst akapitu do niczego nie doprowadzi.

Chodzi o to, że w momencie pojawienia się inputu odpięliśmy zdarzenie od akapitu z opisanych powyżej przyczyn. Teraz musimy w momencie zakończenia edycji podpiąć zdarzenie z powrotem.

Zróbmy to:

javascriptlet elem = document.querySelector('#elem');

elem.addEventListener('click', function func() {
  let input = document.createElement('input');
  input.value = elem.textContent;
  
  elem.textContent = '';
  elem.appendChild(input);
  
  input.addEventListener('blur', function() {
    elem.textContent = this.value;
    elem.addEventListener('click', func); // podpinamy zdarzenie z powrotem
  });
  
  elem.removeEventListener('click', func);
});
Задание 1

Samodzielnie, nie podglądając mojego kodu, rozwiąż opisane zadanie.