일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 데이터모델링과마이닝
- Java
- 자바 공부
- React JS
- 자바
- 코틀린
- 프로그래밍 언어론
- 리액트 훅
- useEffect
- react firebase
- react hook
- 리액트
- vanillaJS
- 자바스크립트
- design pattern
- JavaScript
- 컴퓨터 네트워크
- 프로그래머스 완전탐색
- 프로그래머스
- 디자인 패턴
- react
- 장고
- NextJS
- useState
- codesandbox
- 백준
- 코딩테스트 고득점 Kit
- 프로그래머스 자바
- 코딩테스트 고득점 Kit 완전탐색
- websocket
Archives
- Today
- Total
기록하는 개발자
[vanillaJs] javascript와 html로 영화 card component 만들기 본문
728x90
- 카테고리를 선택하면 해당 카테고리를 tag로 가진 영화들이 화면에 보이게 된다.
- 현재 선택된 카테고리를 보여주기 위해 font-weight를 style로 적용했다.
//Card.js
const movieData = [
{
title: "Sing Street",
date: "2016",
image:
"https://m.media-amazon.com/images/M/MV5BMjEzODA3MDcxMl5BMl5BanBnXkFtZTgwODgxNDk3NzE@._V1_.jpg",
tags: ["all", "music"],
},
{
title: "Tenet",
date: "2020",
image: "http://img.movist.com/?img=/x00/05/32/55_p1.jpg",
tags: ["all", "action", "sf"],
},
{
title: "Ant-man",
date: "2015",
image: "https://i.ebayimg.com/images/g/pvoAAOSwvk9Zgo1i/s-l1600.jpg",
tags: ["all", "fantasy", "adventure"],
},
{
title: "Ant-man and the wasp",
date: "2018",
image:
"https://www.scifinow.co.uk/wp-content/uploads/2018/06/antman_and_the_wasp_ver10_xxlg-768x1115.jpg",
tags: ["all", "fantasy", "adventure"],
},
{
title: "Big Fish",
date: "2003",
image:
"http://image.cine21.com/cine21/poster/2021/0406/12_10_39__606bd12f95ec9.jpg",
tags: ["all", "fantasy", "drama"],
},
{
title: "Interstellar",
date: "2014",
image:
"https://m.media-amazon.com/images/M/MV5BZjdkOTU3MDktN2IxOS00OGEyLWFmMjktY2FiMmZkNWIyODZiXkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_.jpg",
tags: ["all", "adventure", "sf"],
},
{
title: "Little Forest",
date: "2018",
image: "http://img.movist.com/?img=/x00/04/90/83_p1.jpg",
tags: ["all", "drama"],
},
{
title: "Call Me by Your Name",
date: "2017",
image:
"https://m.media-amazon.com/images/M/MV5BNDk3NTEwNjc0MV5BMl5BanBnXkFtZTgwNzYxNTMwMzI@._V1_FMjpg_UX1000_.jpg",
tags: ["all", "drama", "romance"],
},
];
// 모든 card component를 포함하는 최상위 태그
const resources = document.querySelector("#resourcesContainer");
// card component의 부모 노드
const template = document.querySelector("template");
// 버튼에 해당하는 모든 태그
const btnFilter = document.querySelectorAll(".btnFilter");
// 처음 보여줄 category 초기값 all
let category = "all";
let filteredDataResources = [];
// tag 버튼 클릭 시 호출 되는 함수
function fillResourcesContainer() {
//기존 선택되었던 category font의 bold 효과 clear
buttonStyleClear(category);
//category 변수를 클릭 된 버튼의 id로 초기화
category = this.id;
//선택된 category의 font bold 효과
buttonBolder(category);
// 기존 html의 내용을 비우고
clearContainer(resources);
// 새로운 리스트를 보여준다
filterResources(category);
}
//선택된 버튼의 font weight 적용
function buttonBolder(category) {
var clickedButton = document.getElementById(category);
clickedButton.style.fontWeight = 800;
}
//이전에 선택했던 버튼의 font weight 적용 없애기
function buttonStyleClear(category) {
var clickedButton = document.getElementById(category);
clickedButton.style.fontWeight = 500;
}
// 매개변수로 들어온 container의 innerHtml을 ""로 초기화
function clearContainer(container) {
container.innerHTML = "";
}
// 현재 선택 된 카테고리에 대한 영화만 가져오는 함수
function filterResources(category) {
// movieData 중 category에 해당되는 요소만 뽑아 filteredDataResources에 저장
filteredDataResources = movieData.filter((resourceData) => {
//resourceData의 tag 목록에 category가 포함된 경우
if (resourceData.tags.includes(category)) {
// copyTemplateCard 함수를 통해 card conponent를 만들어 resourceCard에 저장
const resourceCard = createCard(resourceData);
//resources 태그의 자식태그로 append
resources.appendChild(resourceCard);
}
});
}
filterResources(category);
//new card component를 만들어내는 함수
function createCard(resourceData) {
// template태그 내 모든 자식 노드까지 복사하여 resourceTemplate 변수에 저장한다.
const resourceTemplate = document.importNode(template.content, true);
// resourceTemplate 내 id가 card-container인 태그를 변수 card에 저장한다.
const card = resourceTemplate.querySelector("#card-container");
//id가 title인 태그의 innerText 지정
const title = card.querySelector("#title");
title.innerText = resourceData.title;
//id가 image인 태그의 src 지정
const image = card.querySelector("#image");
image.src = resourceData.image;
//id가 tagsContainer인 태그 가져오기
const tagsContainer = card.querySelector("#tagsContainer");
//resourceData의 tags 배열 순회
resourceData.tags.map((resourceDataTag) => {
// resourceDataTag에 대해 span 태그 생성
const individualTag = document.createElement("span");
// resourceDataTag가 all이 아닌 경우
if (resourceDataTag !== "all") {
//span의 innerHTML을 resourceDataTag로 초기화
individualTag.innerHTML = `#${resourceDataTag}`;
//tagsContainer의 자식 요소로 붙여넣기
tagsContainer.appendChild(individualTag);
}
});
return card;
}
// 버튼 클릭 시 fillResourcesContainer 함수 호출
btnFilter.forEach(function (btn) {
btn.addEventListener("click", fillResourcesContainer);
});
추가로 createCard 함수에서 사용된 importNode 함수는
노드를 복사하는 함수이다.
아래와 같은 형태로 사용되며 복사에 자식 노드 포함 여부를 정할 수 있다.
const node = document.importNode('복제를 원하는 노드', boolean : 자식 노드 포함 여부);
두 번째 매개변수 : [True인경우 : 자식 노드 포함], [False인 경우 : 자식 노드 미포함]
<-- Home.html -->
<!DOCTYPE html>
<html lang="en">
<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" />
<link rel="stylesheet" type="text/css" href="./card.css" />
</head>
<body>
<section id="button-container">
<button id="all" class="btnFilter">All</button>
<button id="music" class="btnFilter">Music</button>
<button id="fantasy" class="btnFilter">Fantasy</button>
<button id="adventure" class="btnFilter">Adventure</button>
<button id="sf" class="btnFilter">SF</button>
<button id="action" class="btnFilter">Action</button>
<button id="drama" class="btnFilter">Drama</button>
<button id="romance" class="btnFilter">Romance</button>
</section>
<section id="resourcesContainer">
<template>
<article id="card-container">
<div id="card">
<header>
<p id="title"></p>
</header>
<img id="image"></img>
<div id="tagsContainer"></div>
</div>
</article>
</template>
</section>
<script type="text/javascript" src="./Card.js"></script>
</body>
</html>
/* card.css */
#button-container {
border: 1px solid black;
border-radius: 20px;
text-align: center;
padding: 10px 0 10px 0;
width: 60%;
margin: 0 auto;
margin-top: 20px;
margin-bottom: 10px;
}
.btnFilter {
font-size: 15px;
margin: 10px;
padding: 8px;
border-radius: 15px;
border: 1px solid rgb(134, 134, 134);
}
#resourcesContainer {
width: 60%;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
}
#card {
background-color: rgb(233, 233, 233);
width: 200px;
height: 280px;
border-radius: 20px;
text-align: center;
margin: 0 auto;
}
#title {
padding-top: 10px;
font-weight: bold;
}
#image {
height: 180px;
}
#tagsContainer {
height: 40px;
vertical-align: middle;
}
#tagsContainer span {
position: relative;
top: 10px;
padding: 5px;
margin: 3px;
background-color: rgb(255, 255, 255);
border-radius: 5px;
font-size: 14px;
}
참고
https://dev.to/santiagocodes/filtering-component-using-vanilla-js-and-html-content-template-template-element-2iia
https://goodmemory.tistory.com/8
728x90
'Web > Javascript' 카테고리의 다른 글
[vanillaJs] mongoDB, node.js, fetch api로 crud page 만들기-2. frontend (0) | 2022.11.12 |
---|---|
[vanillaJs] mongoDB, node.js, fetch api로 crud page 만들기-1. backend 구성 (0) | 2022.11.12 |
[vanillaJs] Fetch와 Axios를 비교해보자! (0) | 2022.09.03 |
[vanillaJs] 프레임워크없이 SinglePageApplication 만들기-3.동적라우팅 (0) | 2022.09.03 |
[vanillaJs] 정규표현식을 예시와 함께 알아보자! (0) | 2022.09.02 |