<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
a {
color: inherit;
text-decoration: none;
}
.movie-list {
width: 80%;
margin: 0 auto;
}
.movie-list .movie {
float: left;
width: 23%;
height: 500px;
margin-right: 2%;
margin-bottom: 10px;
border: 1px solid gray;
box-sizing: border-box;
padding: 10px;
}
.movie-list .movie .img-box {
width: 100%;
height: 70%;
overflow: hidden;
}
.movie-list .movie .img-box img {
width: 100%;
}
.movie-list .movie .inner {
padding: 25px 15px;
}
.movie-list .movie .inner * {
font-size: 1.3em;
font-weight: 700;
margin-bottom: 5px;
}
.clearfix::after {
content: '';
display: block;
clear: both;
}
header {
width: 100%;
padding: 10px 120px;
box-sizing: border-box;
border-bottom: 2px solid gray;
margin-bottom: 20px;
display: flex;
justify-content: space-between;
}
header h1 {
flex: 1;
}
header .gnb {
flex: 1;
margin-top: 10px;
}
header .gnb ul {
display: flex;
justify-content: space-evenly;
align-items: center;
}
</style>
</head>
<body>
<header>
<h1>WhatSsa!!</h1>
<nav class="gnb">
<ul>
<li><a id="s_rate" href="#">다운로드순</a></li>
<li><a id="s_year" href="#">발매연도순</a></li>
<li><a id="s_like" href="#">좋아요순</a></li>
</ul>
</nav>
</header>
<div class="movie-list clearfix">
<!-- <div class="movie">
<div class="img-box">
<img src="https://yts.mx/assets/images/movies/doctor_who_the_day_of_the_doctor_2013/large-cover.jpg" alt="표지사진">
</div>
<div class="inner">
<div class="title">제목</div>
<div class="year">개봉년도</div>
<div class="rating">평점</div>
</div>
</div> -->
</div>
<!-- Modal -->
<div class="modal fade" id="detailModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">아바타</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<img class="desc-image" src="" alt="" style="width:200px;float: left; margin-right: 20px;">
<p class="movie-description"></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<script>
function makeMovieListDOM(movies) {
let tag = '';
movies.forEach(({id, large_cover_image, title, rating, year}) => {
tag += `
<div class="movie" data-movie-id="${id}" data-bs-toggle="modal" data-bs-target="#detailModal">
<div class="img-box">
<img src="${large_cover_image}" alt="표지사진">
</div>
<div class="inner">
<div class="title">${title}</div>
<div class="year">${year}</div>
<div class="rating">${rating}</div>
</div>
</div>
`;
});
document.querySelector('.movie-list').innerHTML = tag;
}
// 영화 API를 호출하는 함수 (기본값: 다운로드 수)
function fetchMovies(condition='download_count') {
fetch(`https://yts.mx/api/v2/list_movies.json?sort_by=${condition}`)
.then(response => response.json())
.then(json => {
console.log(json.data.movies);
makeMovieListDOM(json.data.movies);
});
}
// 초기영화 정보 로딩
fetchMovies();
// a태그 클릭이벤트
document.querySelector('header .gnb ul').addEventListener('click', e => {
// a태그 링크이동 기능 중지
e.preventDefault();
const id = e.target.id;
switch (id) {
case 's_rate':
fetchMovies('download_count');
break;
case 's_year':
fetchMovies('year');
break;
case 's_like':
fetchMovies('like_count');
break;
}
});
// 영화 상세정보를 모달에 렌더링
function makeMovieDetailDOM({
title, large_cover_image, description_full
}) {
const $modalTitle = document.querySelector('.modal-title');
const $descImg = document.querySelector('.desc-image');
const $summary = document.querySelector('.movie-description');
$modalTitle.textContent = title;
$summary.textContent = description_full;
$descImg.src = large_cover_image;
}
const $movie = document.querySelector('.movie-list');
$movie.addEventListener('click', e => {
if (!e.target.matches('.movie-list .movie *')) return; // 틀 외의 것을 클릭 못하게
// console.log('영화 클릭@');
// console.log(e.target.closest('.movie').dataset.movieId);
const movieId = e.target.closest('.movie').dataset.movieId;
fetch(`https://yts.mx/api/v2/movie_details.json?movie_id=${movieId}`)
.then(res => res.json())
.then(json => {
makeMovieDetailDOM(json.data.movie);
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
댓글내용: <input type="text" id="reply-text">
</div>
<div>
작성자: <input type="text" id="reply-writer">
</div>
<div>
<button id="register">등록</button>
</div>
<p id="reply"></p>
<script>
// GET방식을 제외한 나머지 것들은 두 번째 파라미터 필요
document.getElementById('register').onclick = e => {
const requestInfo = {
method: 'POST',
headers: { // 요청 헤더 정보를 key, value 로 묶음
'content-type': 'application/json'
},
body: JSON.stringify({ /// JS -> JSON으로 변환해서 보냄
text: document.getElementById('reply-text').value,
author: document.getElementById('reply-writer').value,
bno: 102
})
};
fetch('http://localhost:8383/api/v1/replies', requestInfo)
.then(res => res.json())
.then(json => {
document.getElementById('reply').innerHTML = `
${json[0].writer}
`;
})
};
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="remove">삭제!</button>
<script>
document.getElementById('remove').onclick = e => {
const rno = 5016;
fetch(`http://localhost:8383/api/v1/replies/${rno}`, {
method: 'DELETE'
})
.then(res => res.json())
.then(json => {
console.log(json);
})
};
</script>
</body>
</html>
-> 코드의 가독성과 유지보수성을 향상
-> promise대신 promise 안에있는 promiseResult를 한 번에 볼 수 있음
// 일일히 then을 써서 확인 해야하는 한계
function fetchGet() {
const result = fetch('http://localhost:8383/api/v1/replies/100');
// console.log(result);
const json = result.then(res => res.json());
// console.log(json);
const data = json.then(data => {
console.log('then내부:', data);
return '하하호호';
});
console.log('then외부:', data);
}
// async함수는 기본적으로 Promise를 소비하는 함수
async function fetchGet2() {
// await : then 메서드를 대신 호출해서 Promise를 거치지 않고
// PromiseResult를 바로 가져옴
const result = await fetch('http://localhost:8383/api/v1/replies/100');
// console.log(result);
const json = await result.json();
console.log(json);
}
document.getElementById('show').onclick = e => {
fetchGet2();
};
@Param
어노테이션을 사용해서 별칭 부여p.
으로 접근