훈돌라
2024-04-26 개인과제 완성..? 본문
필수 조건들은 모두 들어갔다.. CSS 를 할 힘이 남아있지 않다..



이런 식으로 포스터들이 나열되고, 포스터들은 영화 순위 API 에서 받아온 데이터들을 기반으로
자동 생성되어 html 을 채우게 된다.
페이지 상단의 검색창에 검색어를 입력 후 검색 버튼을 누르면 -> ex ) titan 검색

포스터 제목에 titan 이 포함된 포스터들을 하단에 노출시킨다.
대, 소문자도 상관없다. 로직에 검색 시 데이터들을 읽을 때 소문자로 변환하여 읽게 끔 짜두었기 때문이다.

포스터를 클릭 했을 시 경고창에 해당 영화의 ID 값도 출력되게 끔 구현했다.
과제의 필수 조건
배열 메소드 2개 이상을 제외하고는 모두 완료했다,, 머리를 싸매는 중인데 아직은 forEach 밖에 쓰질 못하겠다..
.then(response => response.json())
.then(response => { // fetch 불러온거 (API)
let movie_list = response.results; // 불러온 데이터를 변수에 할당해준다
let temp_html = ``; // temp_html 을 아무런 값도 없이 초기화 한다
movie_list.forEach(doc => { // 데이터 불러온걸 순회해서 변수들에 넣어준다
let movietitle = doc['name'].replace(' ','-'); // raplace (' ' , '-') id 의 띄어쓰기는 읽지 않음, 그래서 id 의 띄어쓰기를 - (하이픈) 으로 바꾸면 되지 않을까~ 해서 replace 를 사용했음
//The Attack of Titan -> The-Attack-of-Titan
let overview = doc['overview']; //데이터에 변수 지정
let vote_average = doc['vote_average']; //데이터에 변수 지정
let card_id = doc['id']; // 데이터에 변수 지정
|
let movietitle = doc['name'].replace(' ','-')
이 부분에서 상당히 애를 먹었는데, 이유는
name 이라는 영화 이름 데이터를 가져왔을 때 id 값에다 지정을 하니 영화 이름 데이터의 띄어쓰기는 인식하지 못했다.
설명하자면, The Chosen 이라는 영화와 The Owl 이라는 영화가 있다.
근데 ID 값은 띄어쓰기를 인식하지 못하니 이 놈들의 ID 값은 The 가 되는 것이다.


그래서 titan 을 검색하든, hazbin 을 검색하든, 다른 단어를 검색해도 중복되고, 하위에 있는 The Chosen 이라는 영화는 진짜로 무슨
지가 무슨 선택받은 자 (The Chosen) 인 것 마냥 계속 노출되게 되는 것이다. (display none 이 적용이 안 됨)
요컨데, 중복된 ID 값들은 어떻게 해라, 라는 코드가 없었으니 그랬을텐데, 애초에 중복된 영화 이름은 존재할 수 없으니 name 데이터 전부를 읽어올 방법이 없을까? 하는 고민이 시작된 것이다.

li class 의 id 값을 잘 보면 띄어쓰기 까지를 인식하는 것을 확인할 수 있다. 그 이후는 인식하지 않는다.
" Hazbin hotel " 이라면 "Hazbin" 이라고 인식하는 것이다.
let movietitle = doc['name'].replace(' ','-')
그래서 데이터를 불러온 값에 변수 지정을 할 때 데이터를 불러올 때 문자 배열의 ' ' (띄어쓰기) 부분을 ' - ' (하이픈) 으로 바꿔!
라고 코드를 짠것이다. 김래준 매니저님은 천재가 아닐까,, 같이 머리를 싸매며 수십분은 고민을 하다 천재적인 발상을 해내셨다.
아무튼, 데이터 변수 할당에 replace 를 적용시킨다면,

내가 중복되는 값을 어떻게 처리해라 라고 명령을 내리지 않았으니 얼타고 있던 The, The ID 들은 이제 없다.
검색 했을 시 선택받은 자 녀석도 이제는 노출되지 않는다.
요약 = ID 값은 띄어쓰기 전까지만 인식한다.
불러온 데이터의 문자열에 띄어쓰기를 하이픈으로 바꾼다면 해결할수 있다.
const options = {
method: 'GET',
headers: {
accept: 'application/json',
Authorization: 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI3MjI3NzE0MDM1MzEzNjBiZWU2YmRiNmIwZDUwOGVmMiIsInN1YiI6IjY2Mjc1ZTJiNjNkOTM3MDE4Nzc1NjUyZSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.qGlRoILTnebygsMdUJdB_cYmdPsxI-EhBB49Aaja0Pg'
}
};
.then(response => response.json())
.then(response => { // fetch 불러온거 (API)
let movie_list = response.results; // 불러온 데이터를 변수에 할당해준다
let temp_html = ``; // temp_html 을 아무런 값도 없이 초기화 한다
movie_list.forEach(doc => { // 데이터 불러온걸 순회해서 변수들에 넣어준다
let movietitle = doc['name'].replace(' ','-'); // raplace (' ' , '-') id 의 띄어쓰기는 읽지 않음, 그래서 id 의 띄어쓰기를 - (하이픈) 으로 바꾸면 되지 않을까~ 해서 replace 를 사용했음
//The Attack of Titan -> The-Attack-of-Titan
let overview = doc['overview']; //데이터에 변수 지정
let vote_average = doc['vote_average']; //데이터에 변수 지정
let card_id = doc['id']; // 데이터에 변수 지정
// temp_html 의 += 카드 여러개 만든다는 뜻
// html 요소를 만들어서 각 요소에 데이터를 넣는다.
temp_html += `
<li class="item" id=${movietitle} movie-id="${card_id}">
<img src=${image} class="card-image">
<div class="cont">
<strong class="card-title">${movietitle}</strong>
<p >${overview}</p>
<p style="color: chartreuse;">grade : ${vote_average}</p>
</div>
</li>
`;
// fetch 로 데이터를 가져오면서 계속 변경되는 "item" 의 id 값을 ${movietitle} 로 지정해 데이터를 받아온다.
document.getElementById('list_wrap').innerHTML = temp_html;
// 얘가 있어야 적용이 됨, 다큐먼트에 id 값 list_wrap 안에 우리가 만든 temp_html 요소를 넣어준다.
// document = html 전부
// innerHTML = 채워준다
})
// el = 데이터를 표현하기 위한 언어
// id 가 itemcard 인 모든걸 가져온다
// queryselectorAll = document 에서 id 가 itemcard 인 애들을 싹 다 가져온다.
// 가져와서 forEach 해준다
document.querySelectorAll('.item').forEach((el) => {
el.onclick = function () {
let x = el.getAttribute("movie-id"); // getAttribute 요소의 속성을 가지고온다.
alert('영화 ID :' + x);
} // 익명함수 , querySelectorAll , getAttribute
})
})
// DOMContentLoaded 이벤트는 HTML 문서가 완전히 구문 분석되고 모든 지연된 스크립트가 다운로드되고 실행될 때 발생
document.addEventListener('DOMContentLoaded', () => {
const payrollSearch = document.querySelector('#search-input');
// input 박스를 querySelector를 사용하여 지정하고 payrollSearch에 저장
function search() {
// 카드 제목이 포함된 element를 class 값(.item)으로 가져와서 -> familyTitle
const familyTitle = document.querySelectorAll('.item');
// 입력한 검색어의 value값을 가져와 소문자로 변경하여 -> filterValue
const filterValue = payrollSearch.value.toLowerCase();
//console.log("검색어", filterValue)
// familyTitle 안에 있는 문자열을 familyTitle 의 길이만큼 for문으로 순회
for (let i = 0; i < familyTitle.length; i++) {
// 순회하고 있는 familyTitle 의 textContent 를 소문자로 변경 -> rows
let rows = familyTitle[i].textContent.toLowerCase();
//console.log('이거!', payrollTitle[i].parentElement.parentElement)
// 검색된 familyTitle 에 해당하는 카드의 id 값의 속성을 가져와 -> id
const id = familyTitle[i].getAttribute('id');
//rows가 filterValue를 포함하면 해당 title은 보여지게 하고, 그렇지 않으면 숨김
// getElementById를 사용하여 id에 해당하는 카드를 가져온 후
// style.display로 block(보여주기(=빈칸)) 할지 none(숨기기) 할지
if (rows.includes(filterValue)) {
document.getElementById(id).style.display = 'block';
} else {
document.getElementById(id).style.display = 'none';
}
}
}
//querySelector로 검색버튼(#search-button)을 지정하고 click 이벤트로 search 함수 실행
document.querySelector('#search-button').addEventListener('click', search);
|
JS 코드
아직 한 참 부족하다. 문제점도 많을거고, 불필요한 구절도 있을 것이다.그래도 일단은 피드백을 받기 위한 준비는 끝난 것 같고, 내 코드에 대해 설명할 수 있는 힘을 기르면 될 것 같다.이 코드가 왜 쓰여졌고, 왜 이 코드를 쓸 수 밖에 없었냐 = 하는 질문에 대답을 하기가 애매하달까?
아직 JS 문법에 익숙치 않아서도 있겠지만, 코드 짜는 데 시간도 오래 걸렸고, 알고 있는 정보들로
코드를 술 술 짜는 게 아닌 짜면서 필요한걸 검색하면서 짠 느낌이라 그런 것 같기도 하다.
그래도 뭐가 필요하고 어떤 식으로 로직을 짜야할지 정도는 아주 조금? 감이 잡힌 느낌?
변태같은 성향일지 모르겠지만 벽에 부딪혔을 때 이렇게 하면 안 될까? 이게 왜 안 되지? 하면서 콘솔 창도 확인하고콘솔창에 뜬 오류를 따라가면서 해결해나가는 과정이 너무 재밌는 것 같다. 게임 하는 느낌?
하다가 너무 안 되면 튜터님들을 찾아가서 시간 소모를 줄여야 하나? 싶기도 한데 오히려 이렇게 스스로 문제를 찾고 해결 해나가는 시간이 날 성장시키는 시간인 듯 싶다. 뭐, 사람마다 다른거니까.
( 해결 안 되면 당연히 찾아갈거임)