Reputation: 373
I have a code that gets characters names and gender after clicking on film name. This information appears in modal window and my goal is to delete HTML element with characters every time I close modal, so if I select another film the new set of characters will appear, and the old one is already deleted.
The problem is that removeChild
method doesn't work as expected. I've tried different variations including parentNode
but nothing helped.
Here is the code:
window.addEventListener('DOMContentLoaded', function() {
let btn = document.querySelector('.sw-btn');
let content = document.querySelector('.content');
let modal = document.querySelector('.modal');
let modalBody = document.querySelector('.modal-body');
let closeBtn = document.querySelector('.close-btn');
let filmsList = document.createElement('ul');
let charsList = document.createElement('ol');
function getFilms() {
axios.get('https://swapi.co/api/films/').then(res => {
content.appendChild(filmsList);
for (var i = 0; i < res.data.results.length; i++) {
res.data.results.sort(function(a, b) {
let dateA = new Date(a.release_date),
dateB = new Date(b.release_date);
return dateA - dateB;
});
(function updateFilms() {
let addFilm = document.createElement('li');
filmsList.appendChild(addFilm);
let addFilmAnchor = document.createElement('a');
let addFilmId = document.createElement('p');
let addFilmCrawl = document.createElement('p');
let addFilmDirector = document.createElement('p');
let addFilmDate = document.createElement('p');
addFilmAnchor.textContent = res.data.results[i].title;
addFilmId.textContent = `Episode ID: ${res.data.results[i].episode_id}`;
addFilmCrawl.textContent = `Episode description: ${res.data.results[i].opening_crawl}`;
addFilmDirector.textContent = `Episode director: ${res.data.results[i].director}`;
addFilmDate.textContent = `Episode release date: ${res.data.results[i].release_date}`;
addFilm.append(addFilmAnchor, addFilmId, addFilmCrawl, addFilmDirector, addFilmDate);
})();
}
let links = document.getElementsByTagName('a');
for (let j = 0; j < links.length; j++) {
links[j].onclick = function() {
modal.style.display = 'block';
modalBody.appendChild(charsList);
let chars = res.data.results[j].characters;
for (let k = 0; k < chars.length; k++) {
const element = chars[k];
axios.get(element).then(res => {
let addChar = document.createElement('li');
charsList.appendChild(addChar);
let addCharName = document.createElement('p');
let addCharGender = document.createElement('p');
addCharName.textContent = `Character name: ${res.data.name}`;
addCharGender.textContent = `Character gender: ${res.data.gender}`;
addChar.append(addCharName, addCharGender);
})
}
closeBtn.addEventListener('click', () => {
modal.style.display = 'none';
console.log(modalBody.childNodes[0]);
// Problem is here
modalBody.removeChild(modalBody.childNodes[0]);
});
window.addEventListener('click', (e) => {
if (e.target == modal) {
modal.style.display = 'none';
console.log(modalBody.childNodes[0]);
modalBody.removeChild(modalBody.childNodes[0]);
}
})
}
}
}).catch(err => {
console.log("An error occured");
})
};
btn.addEventListener('click', getFilms);
closeBtn.addEventListener('click', () => {
modal.style.display = 'none';
});
window.addEventListener('click', (e) => {
if (e.target == modal) {
modal.style.display = 'none';
}
})
});
body {
max-height: 100vh;
padding: 0;
margin: 0;
font-family: Muli;
}
body::before {
background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Star_Wars_Logo.svg/1200px-Star_Wars_Logo.svg.png') no-repeat center / cover;
background-size: cover;
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -2;
opacity: 0.1;
}
h1 {
text-align: center;
color: #660d41;
font-size: 3em;
margin-top: 10px;
letter-spacing: 1px;
}
main {
display: flex;
align-items: center;
flex-direction: column;
}
.content {
max-width: 55%;
overflow-y: scroll;
max-height: 75vh;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #f4f4f4;
margin: 20% auto;
width: 40%;
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.2);
animation: modalOpen 1s;
}
.modal-header {
background: coral;
padding: 15px;
color: white;
letter-spacing: 1px;
position: relative;
}
.modal-header h2 {
margin: 0;
}
.modal-body {
padding: 10px 20px;
}
.close-btn {
color: white;
float: right;
font-size: 30px;
position: absolute;
top: 0px;
right: 10px;
}
.close-btn:hover,
.close-btn:focus {
color: black;
text-decoration: none;
cursor: pointer;
transition: all 0.4s ease-in;
}
ul {
list-style-type: none;
padding: 10px 20px;
}
li {
border-bottom: 1px solid orangered;
margin-bottom: 30px;
}
li:last-child {
border-bottom: none;
margin-bottom: 0;
}
a {
font-size: 1.7em;
color: #b907d9;
cursor: pointer;
margin-bottom: 10px;
}
p {
font-size: 1.2rem;
color: #0f063f;
margin: 10px 0;
}
button {
padding: .5em 1.5em;
border: none;
color: white;
transition: all 0.2s ease-in;
background: #da2417;
border-radius: 20px;
font-size: 1em;
cursor: pointer;
margin-top: 15px;
}
button:focus {
outline: none;
}
button:hover {
background: #e7736b;
}
button:active {
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.7) inset;
}
@keyframes modalOpen {
from {
opacity: 0
}
to {
opacity: 1
}
}
<link href="https://fonts.googleapis.com/css?family=Muli&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<h1>Star wars films</h1>
<main>
<div class="content"></div>
<div class="modal">
<div class="modal-content">
<div class="modal-header">
<span class="close-btn">×</span>
<h2>Episode Characters</h2>
</div>
<div class="modal-body"></div>
</div>
</div>
<button class="sw-btn">Find Films</button>
</main>
Any help would be appreciated.
Upvotes: 2
Views: 130
Reputation: 877
Do this charsList.innerText = '';
when click close button.
When you call removeChild
you take off the <ol>
from modalbody in UI. You can see the modalBody
is empty after clicking close button.
But you already store the <ol>
element in js variable by let charsList = document.createElement('ol');
so the ol
element itself doesn't change actually.
The <li>
element still inside the <ol>
. Then you add more new <li>
and put it back to modalBody
.
My solution is remove all element in <ol>
when clicking close button.
Upvotes: 0
Reputation: 943
The problem is that you are using the same ol
element when appending the characters to the list, since you instantiate it at the beginning and re-use it later: let charsList = document.createElement('ol');
When you close the modal, you will remove that ol
element from the modal, but you will not remove its content. When opening the modal again, the ol
will be added again - with your old content.
If you move the declaration of charsList
inside your onclick handler, it will work.
Also, you should register the close handlers of your modal only once. Otherwise, it will be called as often as you open your modal.
Demo:
window.addEventListener('DOMContentLoaded', function () {
let btn = document.querySelector('.sw-btn');
let content = document.querySelector('.content');
let modal = document.querySelector('.modal');
let modalBody = document.querySelector('.modal-body');
let closeBtn = document.querySelector('.close-btn');
let filmsList = document.createElement('ul');
closeBtn.addEventListener('click', () => {
modal.style.display = 'none';
console.log(modalBody.childNodes[0]);
modalBody.removeChild(modalBody.childNodes[0]);
});
window.addEventListener('click', (e) => {
if (e.target == modal) {
modal.style.display = 'none';
console.log(modalBody.childNodes[0]);
modalBody.removeChild(modalBody.childNodes[0]);
}
})
function getFilms() {
axios.get('https://swapi.co/api/films/').then(res => {
content.appendChild(filmsList);
for (var i = 0; i < res.data.results.length; i++) {
res.data.results.sort(function (a, b) {
let dateA = new Date(a.release_date),
dateB = new Date(b.release_date);
return dateA - dateB;
});
(function updateFilms() {
let addFilm = document.createElement('li');
filmsList.appendChild(addFilm);
let addFilmAnchor = document.createElement('a');
let addFilmId = document.createElement('p');
let addFilmCrawl = document.createElement('p');
let addFilmDirector = document.createElement('p');
let addFilmDate = document.createElement('p');
addFilmAnchor.textContent = res.data.results[i].title;
addFilmId.textContent = `Episode ID: ${res.data.results[i].episode_id}`;
addFilmCrawl.textContent = `Episode description: ${res.data.results[i].opening_crawl}`;
addFilmDirector.textContent = `Episode director: ${res.data.results[i].director}`;
addFilmDate.textContent = `Episode release date: ${res.data.results[i].release_date}`;
addFilm.append(addFilmAnchor, addFilmId, addFilmCrawl, addFilmDirector, addFilmDate);
})();
}
let links = document.getElementsByTagName('a');
for (let j = 0; j < links.length; j++) {
links[j].onclick = function () {
modal.style.display = 'block';
let charsList = document.createElement('ol');
modalBody.appendChild(charsList);
let chars = res.data.results[j].characters;
for (let k = 0; k < chars.length; k++) {
const element = chars[k];
axios.get(element).then(res => {
let addChar = document.createElement('li');
charsList.appendChild(addChar);
let addCharName = document.createElement('p');
let addCharGender = document.createElement('p');
addCharName.textContent = `Character name: ${res.data.name}`;
addCharGender.textContent = `Character gender: ${res.data.gender}`;
addChar.append(addCharName, addCharGender);
})
}
}
}
}).catch(err => {
console.log("An error occured");
})
};
btn.addEventListener('click', getFilms);
closeBtn.addEventListener('click', () => {
modal.style.display = 'none';
});
window.addEventListener('click', (e) => {
if (e.target == modal) {
modal.style.display = 'none';
}
})
});
body {
max-height: 100vh;
padding: 0;
margin: 0;
font-family: Muli;
}
body::before {
background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Star_Wars_Logo.svg/1200px-Star_Wars_Logo.svg.png') no-repeat center / cover;
background-size: cover;
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -2;
opacity: 0.1;
}
h1 {
text-align: center;
color: #660d41;
font-size: 3em;
margin-top: 10px;
letter-spacing: 1px;
}
main {
display: flex;
align-items: center;
flex-direction: column;
}
.content {
max-width: 55%;
overflow-y: scroll;
max-height: 75vh;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #f4f4f4;
margin: 20% auto;
width: 40%;
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.2);
animation: modalOpen 1s;
}
.modal-header {
background: coral;
padding: 15px;
color: white;
letter-spacing: 1px;
position: relative;
}
.modal-header h2 {
margin: 0;
}
.modal-body {
padding: 10px 20px;
}
.close-btn {
color: white;
float: right;
font-size: 30px;
position: absolute;
top: 0px;
right: 10px;
}
.close-btn:hover,
.close-btn:focus {
color: black;
text-decoration: none;
cursor: pointer;
transition: all 0.4s ease-in;
}
ul {
list-style-type: none;
padding: 10px 20px;
}
li {
border-bottom: 1px solid orangered;
margin-bottom: 30px;
}
li:last-child {
border-bottom: none;
margin-bottom: 0;
}
a {
font-size: 1.7em;
color: #b907d9;
cursor: pointer;
margin-bottom: 10px;
}
p {
font-size: 1.2rem;
color: #0f063f;
margin: 10px 0;
}
button {
padding: .5em 1.5em;
border: none;
color: white;
transition: all 0.2s ease-in;
background: #da2417;
border-radius: 20px;
font-size: 1em;
cursor: pointer;
margin-top: 15px;
}
button:focus {
outline: none;
}
button:hover {
background: #e7736b;
}
button:active {
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.7) inset;
}
@keyframes modalOpen {
from {
opacity: 0
}
to {
opacity: 1
}
}
<link href="https://fonts.googleapis.com/css?family=Muli&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<h1>Star wars films</h1>
<main>
<div class="content"></div>
<div class="modal">
<div class="modal-content">
<div class="modal-header">
<span class="close-btn">×</span>
<h2>Episode Characters</h2>
</div>
<div class="modal-body"></div>
</div>
</div>
<button class="sw-btn">Find Films</button>
</main>
Upvotes: 3