<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">
<script src="https://kit.fontawesome.com/412379eca8.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="style.css">
<script src="main.js"></script>
<title>음식 검색기</title>
</head>
<body>
<div class="container">
<h1>음식 검색기</h1>
<div class="flex">
<form class="flex" id="form">
<input type="text" id="search" placeholder="음식명이나 키워드를 입력하세요">
<button class="search-button" type="submit"><i class="fa-solid fa-magnifying-glass"></i></button>
</form>
<button class="random-button" id="randomBtn"><i class="fa-solid fa-shuffle"></i></button>
</div>
<div id="result-heading">
</div>
<div id="meals" class="meals">
</div>
<div id="single-meal" class="sigleMealContainer">
</div>
</div>
</body>
</html>
*{
box-sizing: border-box;
}
body{
background-color: rgb(89, 57, 57);
margin: 0;
color: white;
}
.container{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.flex{
display: flex;
margin: 0;
}
.flex input{
padding: 8px 10px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border: none;
font-size: 14px;
}
.search-button{
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.flex button{
cursor: pointer;
border: none;
padding: 8px 10px;
font-size: 14px;
}
.random-button{
border-radius: 5px;
margin-left: 5px;
}
.meals{
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
.meal{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
}
.meal-info{
position: absolute;
width: 100%;
height: 100%;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
}
.meal-info:hover{
animation-name: showMealInfo;
animation-duration: 0.5s;
}
.sigleMealContainer{
display: flex;
justify-content: center;
align-items: center;
}
.single-meal{
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
width: 70%;
}
.single-meal h1{
text-align: center;
}
.single-meal-info{
border: 2px dashed #e09;
width: 500px;
margin: 20px;
}
.single-meal-info p{
text-align: center;
}
.main h2{
text-align: center;
}
.main ul{
list-style: none;
}
.main ul li{
display: inline-block;
background-color: #fff;
color: rgb(59, 50, 35);
margin: 5px;
border-radius: 5px;
padding: 8px 10px;
font-weight: bold;
}
img{
width: 200px;
height: 200px;
cursor: pointer;
}
@keyframes showMealInfo{
from{
opacity: 0;
}
to{
opacity: 1;
}
}
fetch(`www.themealdb.com/api/json/v1/1/search.php?s=steak`)
.then(res => res.json())
.then(data => console.log(data));
});
meals.innerHTML = `${data.meals.map(meal => `<div class="meal">
<img src="${meal.strMealThumb}" alt="${meal.strMeal}">
<div class="meal-info">
<h3>${meal.strMeal}</h3>
</div>
</div>`)}`
for(let i= 1; i<= 20; i++){
console.log(data.meals[0].strIngredient`${i}`);
}
이렇게 입력하면 strIngredient 까지만 인식하고 뒤에 숫자를 인식하지 못했다.
for(let i= 1; i<= 20; i++){
console.log(data.meals[0][`strIngredient${i}`]);
}
이렇게 입력하니 잘 인식했다.
(객체에 대해서 더 공부를 해야할 것 같다)
상위 div 에서 margin 0 을 주니 해결됐다.
if (item.classList.contains('meal-info'){...}
처음에 if 문안에 이렇게 적었었는데, 이렇게 적으면 클래스명이 아예 없는 요소도 있기 때문에 검색은 되지만 cannnot define 오류가 발생했다.
if (item.classList) {
return item.classList.contains('meal-info');
} else{ return false};
일단 클래스명이 존재하는지 판단해주고 거기서 meal-info 클래스명을 갖고 있는 요소를 가져왔다.
document.addEventListener("DOMContentLoaded", () => {
const form = document.getElementById("form");
const search = document.getElementById("search");
const resultHeading = document.getElementById("result-heading");
const meals = document.getElementById("meals");
const randomBtn = document.getElementById("randomBtn");
const singleMeal = document.getElementById("single-meal");
// 검색기능
function showMeal(e) {
e.preventDefault();
if (search.value.trim() !== "") {
resultHeading.innerHTML = `<h2>${search.value}의 검색 결과 : </h2>`;
fetch(
`https://www.themealdb.com/api/json/v1/1/search.php?s=${search.value}`
)
.then((res) => res.json())
.then((data) => {
if (data.meals === null) {
resultHeading.innerHTML =
"<p>검색 결과가 없습니다. 다시 시도해주세요!</p>";
} else {
meals.innerHTML = `${data.meals
.map(
(meal) => `<div class="meal">
<img src="${meal.strMealThumb}" alt="${meal.strMeal}">
<div class="meal-info" data-mealID ="${meal.idMeal}">
<h3>${meal.strMeal}</h3>
</div>
</div>`
)
.join("")}`;
console.log(data);
}
});
} else {
alert("키워드를 입력해주세요");
}
search.value = "";
}
//랜덤으로 음식 정보 띄어주기
function showRandomMeal() {
resultHeading.innerHTML = "";
meals.innerHTML = "";
fetch(`https://www.themealdb.com/api/json/v1/1/random.php`)
.then((res) => res.json())
.then((data) => {
let strIngredient = [];
for (let i = 1; i <= 20; i++) {
if (data.meals[0][`strIngredient${i}`] !== "") {
strIngredient.push(
`${data.meals[0][`strIngredient${i}`]} - ${
data.meals[0][`strMeasure${i}`]
}`
);
} else {
break;
}
}
console.log(strIngredient);
const dataMeals = data.meals[0];
makeMealDiv(dataMeals, strIngredient);
});
}
// 음식 정보, 이미지 띄어주기
function makeMealDiv(dataMeals, strIngredient) {
singleMeal.innerHTML = `<div class="single-meal">
<h1>${dataMeals.strMeal}</h1>
<img src="${dataMeals.strMealThumb}" alt="${dataMeals.strMeal}">
<div class="single-meal-info">
<p${dataMeals.strCategory}</p>
<p>${dataMeals.strArea}</p>
</div>
<div class="main">
<p>${dataMeals.strInstructions}</p>
<h2>조리법</h2>
<ul>${strIngredient
.map((item) => `<li>${item}</li>`)
.join("")}</ul>
</div>
</div>`;
}
// 음식 id 가져오기
function getMealID(e) {
const mealInfo = e.composedPath().find(item => {
if (item.classList) {
return item.classList.contains('meal-info');
} else{ return false};
});
if(mealInfo){
const mealID = mealInfo.getAttribute('data-mealID');
showMealDetail(mealID);
}
}
function showMealDetail(mealID){
fetch(`https://www.themealdb.com/api/json/v1/1/lookup.php?i=${mealID}`).then(res => res.json()).then(data =>{
let strIngredient = [];
for (let i = 1; i <= 20; i++) {
if (data.meals[0][`strIngredient${i}`] !== "") {
strIngredient.push(
`${data.meals[0][`strIngredient${i}`]} - ${
data.meals[0][`strMeasure${i}`]
}`
);
} else {
break;
}
}
const dataMeals = data.meals[0];
makeMealDiv(dataMeals, strIngredient);
})
}
form.addEventListener("submit", showMeal);
randomBtn.addEventListener("click", showRandomMeal);
meals.addEventListener("click", getMealID);
});