Skip to content

Commit f14a77e

Browse files
committed
add module 'Document Object Model(DOM)'
1 parent 256cade commit f14a77e

File tree

7 files changed

+1557
-0
lines changed

7 files changed

+1557
-0
lines changed

DOM/README.md

Lines changed: 1043 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
const addMovieModal = document.getElementById("add-modal");
2+
const startAddMovieButton = document.querySelector("header button");
3+
const backdropElement = document.getElementById("backdrop");
4+
const cancelAddMovieModalButton = addMovieModal.querySelector(".btn--passive");
5+
const confirmAddMovieModalButton = cancelAddMovieModalButton.nextElementSibling;
6+
const userInputs = addMovieModal.querySelectorAll("input");
7+
const entryTextSection = document.getElementById("entry-text");
8+
const listRoot = document.getElementById("movie-list");
9+
const deleteMovieModal = document.getElementById("delete-modal");
10+
11+
const movies = [];
12+
let counter = 1;
13+
14+
const updateUI = () => {
15+
if (movies.length === 0) {
16+
entryTextSection.style.display = `block`;
17+
} else {
18+
entryTextSection.style.display = "none";
19+
}
20+
};
21+
22+
const toggleBackdropElement = () => {
23+
backdropElement.classList.toggle("visible");
24+
};
25+
26+
const closeMovieDeletionModal = () => {
27+
toggleBackdropElement();
28+
deleteMovieModal.classList.remove("visible");
29+
};
30+
31+
const deleteMovieHandler = (movieId) => {
32+
let movieIndex = 0;
33+
for (const movie of movies) {
34+
if (movie.id === movieId) {
35+
break;
36+
}
37+
movieIndex++;
38+
}
39+
movies.splice(movieIndex, 1);
40+
listRoot.children[movieIndex].remove();
41+
closeMovieDeletionModal();
42+
updateUI();
43+
};
44+
45+
const startDeleteMovieHandler = (movieId) => {
46+
deleteMovieModal.classList.add("visible");
47+
toggleBackdropElement();
48+
const cancelDeletionButton = deleteMovieModal.querySelector(".btn--passive");
49+
let confirmDeletionButton = deleteMovieModal.querySelector(".btn--danger");
50+
confirmDeletionButton.replaceWith(confirmDeletionButton.cloneNode(true));
51+
confirmDeletionButton = deleteMovieModal.querySelector(".btn--danger");
52+
cancelDeletionButton.removeEventListener("click", closeMovieDeletionModal);
53+
cancelDeletionButton.addEventListener("click", closeMovieDeletionModal);
54+
confirmDeletionButton.addEventListener(
55+
"click",
56+
deleteMovieHandler.bind(null, movieId)
57+
);
58+
};
59+
60+
const renderNewMovieElement = (id, title, imageUrlValue, rating) => {
61+
const newMovieElement = document.createElement("li");
62+
newMovieElement.className = "movie-element";
63+
newMovieElement.innerHTML = `
64+
<div class="movie-element__image">
65+
<img src=${imageUrlValue} alt=${title}/>
66+
</div>
67+
<div class="movie-element__info">
68+
<h2>${title}</h2>
69+
<p>${rating}/5</p>
70+
</div>
71+
`;
72+
newMovieElement.addEventListener(
73+
"click",
74+
startDeleteMovieHandler.bind(null, id)
75+
);
76+
listRoot.append(newMovieElement);
77+
};
78+
79+
const closeMovieModal = () => {
80+
addMovieModal.classList.remove("visible");
81+
};
82+
83+
const showMovieModal = () => {
84+
addMovieModal.classList.add("visible");
85+
toggleBackdropElement();
86+
};
87+
88+
const addMovieHandler = () => {
89+
const titleValue = userInputs[0].value;
90+
const imageUrlValue = userInputs[1].value;
91+
const rating = userInputs[2].value;
92+
if (
93+
titleValue.trim() === "" ||
94+
imageUrlValue.trim() === "" ||
95+
rating.trim() === "" ||
96+
+rating < 1 ||
97+
+rating > 5
98+
) {
99+
alert("Please enter valid values (Rating between 1 and 5)");
100+
return;
101+
}
102+
const newMovie = {
103+
id: counter,
104+
title: titleValue,
105+
image: imageUrlValue,
106+
rating: rating,
107+
};
108+
movies.push(newMovie);
109+
counter++;
110+
console.log(movies);
111+
closeMovieModal();
112+
toggleBackdropElement();
113+
clearMovieInput();
114+
renderNewMovieElement(
115+
newMovie["id"],
116+
newMovie["title"],
117+
newMovie["image"],
118+
newMovie["rating"]
119+
);
120+
updateUI();
121+
};
122+
123+
const clearMovieInput = () => {
124+
for (const usrInp of userInputs) {
125+
usrInp.value = "";
126+
}
127+
};
128+
129+
const cancelAddMovieHandler = () => {
130+
closeMovieModal();
131+
clearMovieInput();
132+
toggleBackdropElement();
133+
};
134+
135+
const backdropClickHandler = () => {
136+
closeMovieModal();
137+
closeMovieDeletionModal();
138+
clearMovieInput();
139+
};
140+
141+
startAddMovieButton.addEventListener("click", showMovieModal);
142+
backdropElement.addEventListener("click", backdropClickHandler);
143+
cancelAddMovieModalButton.addEventListener("click", cancelAddMovieHandler);
144+
confirmAddMovieModalButton.addEventListener("click", addMovieHandler);
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
* {
2+
box-sizing: border-box;
3+
}
4+
5+
html {
6+
font-family: sans-serif;
7+
}
8+
9+
body {
10+
margin: 0;
11+
}
12+
13+
button:focus {
14+
outline: none;
15+
}
16+
17+
header {
18+
width: 100%;
19+
height: 4rem;
20+
display: flex;
21+
justify-content: space-between;
22+
align-items: center;
23+
padding: 0 2.5rem;
24+
background: #00329e;
25+
}
26+
27+
header h1 {
28+
margin: 0;
29+
color: white;
30+
font-size: 1.5rem;
31+
}
32+
33+
header button {
34+
font: inherit;
35+
padding: 0.5rem 1rem;
36+
background: #f67722;
37+
border: 1px solid #f67722;
38+
color: white;
39+
border-radius: 6px;
40+
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.26);
41+
cursor: pointer;
42+
}
43+
44+
header button:hover,
45+
header button:active {
46+
background: #f3cc4b;
47+
border-color: #f3cc4b;
48+
color: #995200;
49+
}
50+
51+
label {
52+
font-weight: bold;
53+
margin: 0.5rem 0;
54+
color: #464646;
55+
}
56+
57+
input {
58+
font: inherit;
59+
border: 1px solid #ccc;
60+
padding: 0.4rem 0.2rem;
61+
color: #383838;
62+
}
63+
64+
input:focus {
65+
outline: none;
66+
background: #fff1c4;
67+
}
68+
69+
.btn {
70+
font: inherit;
71+
padding: 0.5rem 1.5rem;
72+
border: 1px solid #00329e;
73+
background: #00329e;
74+
color: white;
75+
border-radius: 6px;
76+
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.26);
77+
cursor: pointer;
78+
margin: 0 0.5rem;
79+
}
80+
81+
.btn:hover,
82+
.btn:active {
83+
background: #f67722;
84+
border-color: #f67722;
85+
}
86+
87+
.btn--passive {
88+
color: #00329e;
89+
background: transparent;
90+
border: none;
91+
box-shadow: none;
92+
}
93+
94+
.btn--passive:hover,
95+
.btn--passive:active {
96+
background: #aec6f8;
97+
}
98+
99+
.btn--danger {
100+
background: #d30808;
101+
color: white;
102+
border-color: #d30808;
103+
}
104+
105+
.btn--danger:hover,
106+
.btn--danger:active {
107+
background: #ff3217;
108+
border-color: #ff3217;
109+
}
110+
111+
.modal {
112+
position: fixed;
113+
z-index: 100;
114+
background: white;
115+
border-radius: 10px;
116+
width: 80%;
117+
top: 30vh;
118+
left: 10%;
119+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
120+
display: none;
121+
}
122+
123+
.modal.visible {
124+
display: block;
125+
animation: fade-slide-in 0.3s ease-out forwards;
126+
}
127+
128+
.modal .modal__title {
129+
margin: 0;
130+
padding: 1rem;
131+
border-bottom: 1px solid #00329e;
132+
background: #00329e;
133+
color: white;
134+
border-radius: 10px 10px 0 0;
135+
}
136+
137+
.modal .modal__content {
138+
padding: 1rem;
139+
}
140+
141+
.modal .modal__actions {
142+
padding: 1rem;
143+
display: flex;
144+
justify-content: flex-end;
145+
}
146+
147+
.movie-element {
148+
margin: 1rem 0;
149+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
150+
border-radius: 10px;
151+
display: flex;
152+
}
153+
154+
.movie-element h2,
155+
.movie-element p {
156+
font-size: 1.25rem;
157+
margin: 0;
158+
}
159+
160+
.movie-element h2 {
161+
color: #383838;
162+
margin-bottom: 1rem;
163+
}
164+
165+
.movie-element p {
166+
color: white;
167+
display: inline;
168+
background: #f67722;
169+
padding: 0.25rem 1rem;
170+
border-radius: 15px;
171+
}
172+
173+
.movie-element__image {
174+
flex: 1;
175+
border-radius: 10px 0 0 10px;
176+
overflow: hidden;
177+
}
178+
179+
.movie-element__image img {
180+
height: 100%;
181+
width: 100%;
182+
object-fit: cover;
183+
}
184+
185+
.movie-element__info {
186+
flex: 2;
187+
padding: 1rem;
188+
}
189+
190+
.card {
191+
background: white;
192+
border-radius: 10px;
193+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
194+
}
195+
196+
#entry-text {
197+
width: 40rem;
198+
margin: 2rem auto;
199+
max-width: 80%;
200+
padding: 1rem;
201+
}
202+
203+
#entry-text p {
204+
font-size: 1.5rem;
205+
text-align: center;
206+
}
207+
208+
#movie-list {
209+
list-style: none;
210+
width: 40rem;
211+
max-width: 90%;
212+
margin: 1rem auto;
213+
padding: 0;
214+
}
215+
216+
#backdrop {
217+
position: fixed;
218+
width: 100%;
219+
height: 100vh;
220+
top: 0;
221+
left: 0;
222+
background: rgba(0, 0, 0, 0.75);
223+
z-index: 10;
224+
pointer-events: none;
225+
display: none;
226+
}
227+
228+
#backdrop.visible {
229+
display: block;
230+
pointer-events: all;
231+
}
232+
233+
#add-modal .modal__content {
234+
display: flex;
235+
flex-direction: column;
236+
}
237+
238+
@media (min-width: 768px) {
239+
.modal {
240+
width: 40rem;
241+
left: calc(50% - 20rem);
242+
}
243+
}
244+
245+
@keyframes fade-slide-in {
246+
from {
247+
transform: translateY(-5rem);
248+
}
249+
to {
250+
transform: translateY(0);
251+
}
252+
}

0 commit comments

Comments
 (0)