<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Searching & highlight</title>
<style>
.highlight {
background-color: yellow;
}
</style>
</head>
<body>
<h1>2. 검색이 필요해</h1>
<hr />
<main>
<label>Search:</label>
<input type="text" id="search-input" />
<ul id="search-history"></ul>
<section id="section"></section>
</main>
<a href="./index.html" class="back-link">← 뒤로가기</a>
</body>
</html>
let data = [];
const fetchData = async () => {
const response = await fetch("index2.json");
const arr = await response.json();
data.push(...arr);
// 1. 렌더링 먼저
renderTable(data);
};
const renderTable = (data) => {
const section = document.getElementById("section");
const table = document.createElement("table");
section.appendChild(table);
const headers = ["ID", "Photographer", "Introduction"];
const headerRow = document.createElement("tr");
headers.forEach((headerText) => {
const header = document.createElement("th");
header.textContent = headerText;
headerRow.appendChild(header);
});
table.appendChild(headerRow);
const rows = data.map((element) => {
const row = document.createElement("tr");
const idCell = document.createElement("td");
idCell.textContent = element.id;
row.appendChild(idCell);
const PhotographerCell = document.createElement("td");
PhotographerCell.textContent = element.photographer;
row.appendChild(PhotographerCell);
const IntroductionCell = document.createElement("td");
IntroductionCell.textContent = element.introduction;
row.appendChild(IntroductionCell);
return row;
});
rows.forEach((row) => {
table.appendChild(row);
});
};
// 2. 데이터 패칭
fetchData();
// 검색할 때 돌아가는 코드
let filteredData = [];
searchInput.addEventListener("input", handleSearch);
// 입력한 텍스트가 포함되면 필터링된 배열에 필터링하기
function handleSearch(event) {
const searchText = event.target.value.toLowerCase();
if (searchText === "") {
renderTable(searchData);
return;
}
filteredData = data.filter((item) => {
return (
String(item.id).toLowerCase().includes(searchText) ||
item.photographer.toLowerCase().includes(searchText) ||
item.introduction.toLowerCase().includes(searchText)
);
});
renderTable(filteredData);
}
// 정규식 객체 regex가 true인 애들은 span으로 대체해버리기
function highlightSearchText(searchText, text) {
const regex = new RegExp(`${searchText}`, "gi");
return text.replace(
regex,
`<span class="highlight">${searchText}</span>`
);
}
// 모든 문장을 순회하면서, 검색 텍스트가 포함되면 하이라이트
function applyHighlighting(searchText) {
const rows = document.querySelectorAll("table tr");
rows.forEach((row) => {
const cells = row.querySelectorAll("td");
cells.forEach((cell) => {
const originalText = cell.textContent;
const highlightedText = highlightSearchText(
searchText,
originalText
);
cell.innerHTML = highlightedText;
});
});
}
// 일단 공백없이 입력하게 하기
searchInput.addEventListener("input", (event) => {
const searchText = event.target.value.trim();
applyHighlighting(searchText);
});
// 검색 히스토리 코드 작성
const searchHistoryLimit = 5;
const searchHistoryList = document.getElementById("search-history");
let searchHistory = [];
// 입력하고 Enter 치면
// 이미 입력했거나 아예 입력하지 않으면 기록안됨
// 최신순으로 입력되게 하기
// 5개 넘으면 오래된거 지워지게하기
// 검색기록은 로컬스토리지에 담아서 계속 남아있게하기
// 그리고 기록되고난후 입력창은 빈칸
// 그리고 원래대로 내용 렌더링하고
// 화면에 검색기록 렌더링하기
// 검색기록은 로컬스토리지에서 가져오기
searchInput.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
const searchText = searchInput.value.trim();
if (searchHistory.includes(searchText) || searchText === "") {
return;
}
searchHistory.unshift(searchText);
if (searchHistory.length > searchHistoryLimit) {
searchHistory.pop();
}
localStorage.setItem(
"searchHistory",
JSON.stringify(searchHistory)
);
searchInput.value = "";
renderTable(searchData);
updateSearchHistory();
}
});
function updateSearchHistory() {
searchHistoryList.innerHTML = "";
searchHistory.forEach((searchText) => {
const listItem = document.createElement("li");
listItem.textContent = searchText;
searchHistoryList.appendChild(listItem);
});
}
if (localStorage.getItem("searchHistory")) {
searchHistory = JSON.parse(localStorage.getItem("searchHistory"));
}
updateSearchHistory();
검색 기능
<input>
요소를 통해 검색어를 입력할 수 있습니다.input
이벤트가 발생하고 입력된 검색어를 받아와서 처리합니다.searchData
를 필터링합니다.data
배열에서 검색어가 ID
, Photographer
, 또는 Introduction
에 포함된 항목들로 이루어진 filteredData
배열을 생성합니다.renderTable
함수를 호출하여 filteredData
를 기반으로 테이블을 업데이트하여 검색 결과를 화면에 표시합니다.검색 하이라이트 기능
highlightSearchText
함수는 정규식을 사용하여 검색어와 일치하는 텍스트를 <span>
요소로 감싸 하이라이트 효과를 줍니다.applyHighlighting
함수는 모든 테이블 셀을 순회하면서 검색어와 일치하는 텍스트를 찾아 highlightSearchText
함수를 사용하여 하이라이트 효과를 적용합니다.applyHighlighting
함수가 호출되어 화면에 검색어가 하이라이트된 텍스트가 표시됩니다.검색 히스토리 기능
Enter
키를 누를 경우, 검색어를 검사하여 기존 검색 기록에 없고 공백이 아닐 경우에만 검색 히스토리에 추가됩니다.updateSearchHistory
함수가 호출되어 로컬 스토리지에서 검색 히스토리를 가져와 화면에 표시합니다.<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Searching & highlight</title>
<style>
.highlight {
background-color: yellow;
}
</style>
</head>
<body>
<h1>2. 검색이 필요해</h1>
<hr />
<main>
<label>Search:</label>
<input type="text" id="search-input" />
<ul id="search-history"></ul>
<section id="section"></section>
</main>
<a href="./index.html" class="back-link">← 뒤로가기</a>
<script>
let data = [];
const fetchData = async () => {
const response = await fetch("index2.json");
const arr = await response.json();
data.push(...arr);
// 1. 렌더링 먼저
renderTable(data);
};
const renderTable = (data) => {
const section = document.getElementById("section");
const table = document.createElement("table");
section.appendChild(table);
const headers = ["ID", "Photographer", "Introduction"];
const headerRow = document.createElement("tr");
headers.forEach((headerText) => {
const header = document.createElement("th");
header.textContent = headerText;
headerRow.appendChild(header);
});
table.appendChild(headerRow);
const rows = data.map((element) => {
const row = document.createElement("tr");
const idCell = document.createElement("td");
idCell.textContent = element.id;
row.appendChild(idCell);
const PhotographerCell = document.createElement("td");
PhotographerCell.textContent = element.photographer;
row.appendChild(PhotographerCell);
const IntroductionCell = document.createElement("td");
IntroductionCell.textContent = element.introduction;
row.appendChild(IntroductionCell);
return row;
});
rows.forEach((row) => {
table.appendChild(row);
});
};
// 2. 데이터 패칭
fetchData();
window.onload = function () {
const currentUrl = window.location.href;
if (currentUrl.includes("web")) {
const link = document.querySelector(".back-link");
link.href = "../";
}
};
</script>
<script>
window.addEventListener("DOMContentLoaded", () => {
const searchInput = document.getElementById("search-input");
const section = document.getElementById("section");
let searchData = [];
const fetchData = async () => {
const response = await fetch("index2.json");
const arr = await response.json();
searchData.push(...arr);
// 2. 렌더링
renderTable(searchData);
};
function renderTable(data) {
section.innerHTML = "";
const table = document.createElement("table");
section.appendChild(table);
const headers = ["ID", "Photographer", "Introduction"];
const headerRow = document.createElement("tr");
headers.forEach((headerText) => {
const header = document.createElement("th");
header.textContent = headerText;
headerRow.appendChild(header);
});
table.appendChild(headerRow);
data.forEach((element) => {
const row = document.createElement("tr");
const idCell = document.createElement("td");
idCell.textContent = element.id;
row.appendChild(idCell);
const PhotographerCell = document.createElement("td");
PhotographerCell.textContent = element.photographer;
row.appendChild(PhotographerCell);
const IntroductionCell = document.createElement("td");
IntroductionCell.textContent = element.introduction;
row.appendChild(IntroductionCell);
table.appendChild(row);
});
}
// 1. 데이터 패칭
fetchData();
// 검색할 때 돌아가는 코드
let filteredData = [];
searchInput.addEventListener("input", handleSearch);
// 입력한 텍스트가 포함되면 필터링된 배열에 필터링하기
function handleSearch(event) {
const searchText = event.target.value.toLowerCase();
if (searchText === "") {
renderTable(searchData);
return;
}
filteredData = data.filter((item) => {
return (
String(item.id).toLowerCase().includes(searchText) ||
item.photographer.toLowerCase().includes(searchText) ||
item.introduction.toLowerCase().includes(searchText)
);
});
renderTable(filteredData);
}
// 정규식 객체 regex가 true인 애들은 span으로 대체해버리기
function highlightSearchText(searchText, text) {
const regex = new RegExp(`${searchText}`, "gi");
return text.replace(
regex,
`<span class="highlight">${searchText}</span>`
);
}
// 모든 문장을 순회하면서, 검색 텍스트가 포함되면 하이라이트
function applyHighlighting(searchText) {
const rows = document.querySelectorAll("table tr");
rows.forEach((row) => {
const cells = row.querySelectorAll("td");
cells.forEach((cell) => {
const originalText = cell.textContent;
const highlightedText = highlightSearchText(
searchText,
originalText
);
cell.innerHTML = highlightedText;
});
});
}
// 일단 공백없이 입력하게 하기
searchInput.addEventListener("input", (event) => {
const searchText = event.target.value.trim();
applyHighlighting(searchText);
});
// 검색 히스토리 코드 작성
const searchHistoryLimit = 5;
const searchHistoryList = document.getElementById("search-history");
let searchHistory = [];
// 입력하고 Enter 치면
// 이미 입력했거나 아예 입력하지 않으면 기록안됨
// 최신순으로 입력되게 하기
// 5개 넘으면 오래된거 지워지게하기
// 검색기록은 로컬스토리지에 담아서 계속 남아있게하기
// 그리고 기록되고난후 입력창은 빈칸
// 그리고 원래대로 내용 렌더링하고
// 화면에 검색기록 렌더링하기
// 검색기록은 로컬스토리지에서 가져오기
searchInput.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
const searchText = searchInput.value.trim();
if (searchHistory.includes(searchText) || searchText === "") {
return;
}
searchHistory.unshift(searchText);
if (searchHistory.length > searchHistoryLimit) {
searchHistory.pop();
}
localStorage.setItem(
"searchHistory",
JSON.stringify(searchHistory)
);
searchInput.value = "";
renderTable(searchData);
updateSearchHistory();
}
});
function updateSearchHistory() {
searchHistoryList.innerHTML = "";
searchHistory.forEach((searchText) => {
const listItem = document.createElement("li");
listItem.textContent = searchText;
searchHistoryList.appendChild(listItem);
});
}
if (localStorage.getItem("searchHistory")) {
searchHistory = JSON.parse(localStorage.getItem("searchHistory"));
}
updateSearchHistory();
});
</script>
</body>
</html>