728x90
오늘은 검색한 결과를 wikipedia에서 가져오는 프로젝트를 만들어보겠습니다.
index.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" />
<title>Wikipedia</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<section class="wiki">
<div class="container">
<img src="./wiki-logo.png" alt="logo" />
<h3>Search Wikipedia</h3>
<form class="form">
<input type="text" class="form-input" />
<button type="submit" class="submit-btn">search</button>
</form>
</div>
<!-- results -->
<div class="results"></div>
</section>
<script src="./app.js"></script>
</body>
</html>
styles.css
*,
::after,
::before {
box-sizing: border-box;
}
html {
font-size: 100%;
} /*16px*/
:root {
/* colors */
--primary-100: #e2e0ff;
--primary-200: #c1beff;
--primary-300: #a29dff;
--primary-400: #837dff;
--primary-500: #645cff;
--primary-600: #504acc;
--primary-700: #3c3799;
--primary-800: #282566;
--primary-900: #141233;
/* grey */
--grey-50: #f8fafc;
--grey-100: #f1f5f9;
--grey-200: #e2e8f0;
--grey-300: #cbd5e1;
--grey-400: #94a3b8;
--grey-500: #64748b;
--grey-600: #475569;
--grey-700: #334155;
--grey-800: #1e293b;
--grey-900: #0f172a;
/* rest of the colors */
--black: #222;
--white: #fff;
--red-light: #f8d7da;
--red-dark: #842029;
--green-light: #d1e7dd;
--green-dark: #0f5132;
/* fonts */
--small-text: 0.875rem;
--extra-small-text: 0.7em;
/* rest of the vars */
--backgroundColor: var(--grey-50);
--textColor: var(--grey-900);
--borderRadius: 0.25rem;
--letterSpacing: 1px;
--transition: 0.3s ease-in-out all;
--max-width: 1120px;
--fixed-width: 600px;
/* box shadow*/
--shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
--shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
0 4px 6px -2px rgba(0, 0, 0, 0.05);
--shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1),
0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
body {
background: var(--backgroundColor);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-weight: 400;
line-height: 1.75;
color: var(--textColor);
}
p {
margin-bottom: 1.5rem;
max-width: 40em;
}
h1,
h2,
h3,
h4,
h5 {
margin: 0;
margin-bottom: 1.38rem;
font-weight: 400;
line-height: 1.3;
text-transform: capitalize;
letter-spacing: var(--letterSpacing);
}
h1 {
margin-top: 0;
font-size: 3.052rem;
}
h2 {
font-size: 2.441rem;
}
h3 {
font-size: 1.953rem;
}
h4 {
font-size: 1.563rem;
}
h5 {
font-size: 1.25rem;
}
small,
.text-small {
font-size: var(--small-text);
}
a {
text-decoration: none;
}
ul {
list-style-type: none;
padding: 0;
}
.img {
width: 100%;
display: block;
object-fit: cover;
}
/* buttons */
.btn {
cursor: pointer;
color: var(--white);
background: var(--primary-500);
border: transparent;
border-radius: var(--borderRadius);
letter-spacing: var(--letterSpacing);
padding: 0.375rem 0.75rem;
box-shadow: var(--shadow-1);
transition: var(--transition);
text-transform: capitalize;
display: inline-block;
}
.btn:hover {
background: var(--primary-700);
box-shadow: var(--shadow-3);
}
@keyframes spinner {
to {
transform: rotate(360deg);
}
}
.loading {
width: 6rem;
height: 6rem;
border: 5px solid var(--grey-400);
border-radius: 50%;
border-top-color: var(--primary-500);
animation: spinner 0.6s linear infinite;
}
.loading {
margin: 0 auto;
margin-top: 4rem;
}
/* title */
.title {
text-align: center;
margin-bottom: 3rem;
}
.title-underline {
background: var(--primary-500);
width: 7rem;
height: 0.25rem;
margin: 0 auto;
margin-top: -1rem;
}
/*
===============
Wikipedia
===============
*/
.wiki {
padding: 5rem 0;
width: 90vw;
max-width: 1170px;
margin: 0 auto;
}
.container {
text-align: center;
}
.container img {
width: 200px;
}
.container h3 {
margin-bottom: 2rem;
}
.form {
background: #fff;
width: 100%;
margin: 0 auto;
padding: 2.5rem;
border-radius: var(--borderRadius);
display: grid;
grid-template-columns: auto 100px;
}
.form-input,
.submit-btn {
padding: 0.375rem 0.75rem;
background: var(--backgroundColor);
border: 1px solid var(--grey-200);
}
.form-input {
border-right: transparent;
border-top-left-radius: var(--borderRadius);
border-bottom-left-radius: var(--borderRadius);
}
.submit-btn {
border: 1px solid var(--primary-500);
border-left: transparent;
border-top-right-radius: var(--borderRadius);
border-bottom-right-radius: var(--borderRadius);
text-transform: capitalize;
background: var(--primary-500);
color: var(--white);
transition: var(--transition);
cursor: pointer;
}
.submit-btn:hover {
color: var(--primary-900);
}
.results {
padding: 2rem 0;
}
.error {
text-align: center;
text-transform: capitalize;
color: var(--red-dark);
}
.articles {
display: grid;
gap: 1rem;
}
.articles a {
display: block;
background: var(--white);
color: var(--textColor);
padding: 1.5rem 2rem;
border-radius: var(--borderRadius);
transition: var(--transition);
}
.articles p {
color: var(--grey-500);
transition: var(--transition);
}
.articles a:hover {
background: var(--black);
color: var(--white);
}
@media screen and (min-width: 768px) {
.articles {
grid-template-columns: 1fr 1fr;
}
.form {
max-width: 600px;
}
}
@media screen and (min-width: 992px) {
.articles {
grid-template-columns: 1fr 1fr 1fr;
}
}
app.js
// 위키피디아 API 검색을 위한 URL 엔드포인트
const url =
"https://en.wikipedia.org/w/api.php?action=query&list=search&srlimit=20&format=json&origin=*&srsearch=";
// DOM에서 폼, 입력 및 결과 요소 선택
const formDOM = document.querySelector(".form");
const inputDOM = document.querySelector(".form-input");
const resultsDOM = document.querySelector(".results");
// 폼 제출을 처리하기 위해 이벤트 리스너 추가
formDOM.addEventListener("submit", (e) => {
e.preventDefault(); // 기본 폼 제출 동작 방지
const value = inputDOM.value; // 입력 값 가져오기
if (!value) {
// 입력이 비어있으면 오류 메시지 표시
resultsDOM.innerHTML =
'<div class="error"> 유효한 검색어를 입력하세요</div>';
return;
}
fetchPages(value); // 입력 값으로 fetchPages 함수 호출
});
// 검색 값에 따라 위키피디아 API에서 페이지를 가져오는 함수
const fetchPages = async (searchValue) => {
resultsDOM.innerHTML = '<div class="loading"></div>'; // 로딩 메시지 표시
try {
const response = await fetch(`${url}${searchValue}`); // API에서 데이터 가져오기
const data = await response.json(); // JSON 응답 파싱
const results = data.query.search; // 응답에서 검색 결과 가져오기
if (results.length < 1) {
// 결과가 없으면 오류 메시지 표시
resultsDOM.innerHTML =
'<div class="error">일치하는 결과가 없습니다. 다시 시도하세요</div>';
return;
}
renderResults(results); // 검색 결과로 renderResults 함수 호출
} catch (error) {
// 가져오는 동안 오류가 발생하면 오류 메시지 표시
resultsDOM.innerHTML = '<div class="error"> 오류가 발생했습니다...</div>';
}
};
// 페이지에 검색 결과를 렌더링하는 함수
const renderResults = (list) => {
const cardsList = list
.map((item) => {
const { title, snippet, pageid } = item; // title, snippet 및 pageid를 가져오기 위해 item 디스트럭처링
return `<a href=http://en.wikipedia.org/?curid=${pageid} target="_blank">
<h4>${title}</h4>
<p>
${snippet}
</p>
</a>`; // 제목, 스니펫 및 위키피디아 페이지 링크가 포함된 앵커 태그 생성
})
.join(""); // 앵커 태그 배열을 하나의 문자열로 결합
resultsDOM.innerHTML = `<div class="articles">
${cardsList}
</div>`; // 페이지에 검색 결과 표시
};
wiki-urls.js
const url =
"https://en.wikipedia.org/w/api.php?action=query&list=search&srlimit=20&format=json&origin=*&srsearch=searchValue";
// list=search - 전체 텍스트 검색 수행
// srsearch="inputValue" - 이 값과 일치하는 페이지 제목이나 내용을 검색
// srlimit=20 - 반환할 총 페이지 수
// format=json - JSON 응답 형식
// "origin=*" - CORS 오류 해결
const page_url = "href=http://en.wikipedia.org/?curid=${pageid}";
'JavaScript' 카테고리의 다른 글
[Javascript] dad joke 만들기 (0) | 2024.06.28 |
---|---|
[Javascript] stripe만들기 (0) | 2024.06.23 |
[Javascript] 화면내에 공 키보드로 이동 시키기 (0) | 2024.06.17 |
[JavaScript] 아이템 슬라이드 (0) | 2024.06.13 |
[JavaScript] 아이템 동적추가 삭제 (0) | 2024.06.07 |