[260111] 프로젝트 이전 및 초기화
This commit is contained in:
991
cardList.html
Normal file
991
cardList.html
Normal file
@@ -0,0 +1,991 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<title>Card List</title>
|
||||
<script src="/script/navigation.js"></script>
|
||||
<script type="module" src="/i18n/i18n.js"></script>
|
||||
<link href="/style/navigation.css" rel="stylesheet" />
|
||||
<link href="/style/style.css" rel="stylesheet" />
|
||||
<link href="/style/output.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<style>
|
||||
.homeview_container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.ads_coupang iframe {
|
||||
max-height: 96px;
|
||||
}
|
||||
@media screen and (min-width: 640px) {
|
||||
.ads_coupang {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.homeview_container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
.ads_coupang iframe {
|
||||
max-height: 128px;
|
||||
}
|
||||
}
|
||||
#cardList {
|
||||
padding-bottom: 128px;
|
||||
}
|
||||
</style>
|
||||
<div id="app">
|
||||
<!-- 로딩 -->
|
||||
<div
|
||||
id="loading-screen"
|
||||
class="fixed top-0 left-0 w-full h-full bg-white flex justify-center items-center"
|
||||
>
|
||||
<div
|
||||
class="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-gray-900"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<div class="homeview_container max-w-6xl lg:max-w-7xl mx-auto">
|
||||
<div class="sm:col-span-1">
|
||||
<div
|
||||
class="aside-widget w-full mx-auto max-w-2xl sm:max-w-4xl lg:max-w-5xl xl:max-w-7xl flex gap-1 justify-between px-4 xl:px-2 sm:mt-20"
|
||||
>
|
||||
<div class="w-full flex flex-col gap-2 transition-all">
|
||||
<div class="">
|
||||
<div class="relative">
|
||||
<label
|
||||
for="name"
|
||||
class="absolute -top-2 left-2 inline-block bg-white px-1 text-xs font-medium text-gray-900"
|
||||
>Card Search</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
id="searchQuery"
|
||||
class="block w-full rounded-md border-0 px-3 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
placeholder="ex) UA04BT/IMS-1-082"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<h4 class="mt-4 font-bold text-lg">COLOR</h4>
|
||||
<div class="flex flex-wrap gap-2 mt-4">
|
||||
<button
|
||||
type="button"
|
||||
class="color-filter-btn px-3 py-1 rounded border"
|
||||
data-color="All"
|
||||
>
|
||||
All
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="color-filter-btn px-3 py-1 rounded"
|
||||
data-color="Red"
|
||||
>
|
||||
Red
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="color-filter-btn px-3 py-1 rounded"
|
||||
data-color="Blue"
|
||||
>
|
||||
Blue
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="color-filter-btn px-3 py-1 rounded"
|
||||
data-color="Green"
|
||||
>
|
||||
Green
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="color-filter-btn px-3 py-1 rounded"
|
||||
data-color="Yellow"
|
||||
>
|
||||
Yellow
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="color-filter-btn px-3 py-1 rounded"
|
||||
data-color="Purple"
|
||||
>
|
||||
Purple
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="color-filter-btn px-3 py-1 rounded"
|
||||
data-color="AP"
|
||||
>
|
||||
AP
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="color-filter-btn px-3 py-1 rounded"
|
||||
data-color="Multi"
|
||||
>
|
||||
Multi
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col aside-accordion-widget">
|
||||
<h4 class="mt-4 font-bold text-lg">TYPE</h4>
|
||||
<div
|
||||
class="checkbox-wrapper w-full flex flex-col gap-2 items-start py-2"
|
||||
>
|
||||
<div>
|
||||
<input id="includeBasic" type="checkbox" checked />
|
||||
<label for="includeBasic" data-i18n="includeBasic"></label>
|
||||
</div>
|
||||
<div>
|
||||
<input id="includeAP" type="checkbox" />
|
||||
<label
|
||||
for="includeAP"
|
||||
data-i18n="includeActionPoint"
|
||||
></label>
|
||||
</div>
|
||||
<div>
|
||||
<input id="includeParallel" type="checkbox" />
|
||||
<label
|
||||
for="includeParallel"
|
||||
data-i18n="includeParallel"
|
||||
></label>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="mt-4 font-bold text-lg">TRIGGER</h4>
|
||||
<div class="radio-wrapper w-full flex flex-col gap-2 py-2">
|
||||
<div>
|
||||
<input
|
||||
id="includeAllTrigger"
|
||||
type="radio"
|
||||
name="triggerType"
|
||||
value="allTrigger"
|
||||
checked
|
||||
/>
|
||||
<label
|
||||
for="includeAllTrigger"
|
||||
class="ml-2"
|
||||
data-i18n="includeAllTrigger"
|
||||
>Include All Trigger</label
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
id="includeColorTrigger"
|
||||
type="radio"
|
||||
name="triggerType"
|
||||
value="colorTrigger"
|
||||
/>
|
||||
<label
|
||||
for="includeColorTrigger"
|
||||
class="ml-2"
|
||||
data-i18n="includeColorTrigger"
|
||||
>Include Color Trigger</label
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
id="includeSpecialTrigger"
|
||||
type="radio"
|
||||
name="triggerType"
|
||||
value="specialTrigger"
|
||||
/>
|
||||
<label
|
||||
for="includeSpecialTrigger"
|
||||
class="ml-2"
|
||||
data-i18n="includeSpecialTrigger"
|
||||
>Include Special Trigger</label
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
id="includeFinalTrigger"
|
||||
type="radio"
|
||||
name="triggerType"
|
||||
value="finalTrigger"
|
||||
/>
|
||||
<label
|
||||
for="includeFinalTrigger"
|
||||
class="ml-2"
|
||||
data-i18n="includeFinalTrigger"
|
||||
>Include Final Trigger</label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="SelectedSeriesCardList col-span-3 mt-4 sm:mt-0">
|
||||
<div
|
||||
id="totalCount"
|
||||
class="result_total_count text-center text-xl mb-8"
|
||||
>
|
||||
<span data-i18n="SearchResults"></span>:
|
||||
<span id="SearchResultsCounter">0</span>
|
||||
<span data-i18n="SearchResultsCounter"></span>
|
||||
</div>
|
||||
<div id="cardList">
|
||||
<div
|
||||
class="mx-auto max-w-2xl mb-24 px-4 sm:px-6 sm:max-w-4xl lg:max-w-5xl lg:px-8 xl:max-w-7xl"
|
||||
>
|
||||
<div
|
||||
class="mt-6 grid grid-cols-3 gap-x-6 gap-y-6 lg:grid-cols-4 lg:gap-x-5 xl:grid-cols-5 xl:gap-x-8"
|
||||
id="card-grid"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full fixed bottom-0 z-50">
|
||||
<!-- 프리뷰 버튼 -->
|
||||
<div class="w-full go-result-page-btn rounded-t-xl">
|
||||
<!-- Coupang -->
|
||||
<div class="ads_coupang">
|
||||
<iframe
|
||||
src="https://ads-partners.coupang.com/widgets.html?id=915533&template=carousel&trackingCode=AF6561083&subId=&width=1280&height=128&tsource="
|
||||
width="100%"
|
||||
height="128"
|
||||
frameborder="0"
|
||||
scrolling="no"
|
||||
referrerpolicy="unsafe-url"
|
||||
browsingtopics
|
||||
></iframe>
|
||||
</div>
|
||||
<div
|
||||
id="goToResultPage"
|
||||
class="w-full h-12 cursor-pointer flex justify-center items-center bg-indigo-500 px-3 py-2 font-semibold text-white shadow-sm hover:bg-indigo-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500"
|
||||
data-i18n="makeDeckList"
|
||||
></div>
|
||||
</div>
|
||||
<!-- 푸터 카드 현황 -->
|
||||
<div
|
||||
class="bottom-line w-full bg-black text-white text-center text-sm flex gap-4 justify-around items-center z-50"
|
||||
>
|
||||
<div class="copyright hidden sm:block">
|
||||
KEY CARD: <span id="keyCardCount">0</span>/4
|
||||
</div>
|
||||
<div class="flex gap-4 select-none">
|
||||
<div id="colorCount">
|
||||
COLOR: <span id="colorCardCount">0</span>/4
|
||||
</div>
|
||||
<span>|</span>
|
||||
<div id="finalCount">
|
||||
FINAL: <span id="finalCardCount">0</span>/4
|
||||
</div>
|
||||
<span>|</span>
|
||||
<div id="specialCount">
|
||||
SPECIAL: <span id="specialCardCount">0</span>/4
|
||||
</div>
|
||||
<span>|</span>
|
||||
<div id="totalCardsCount">
|
||||
TOTAL: <span id="totalCardCount">0</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="imageOverlay" class="overlay">
|
||||
<img src="" alt="Card Preview" />
|
||||
</div>
|
||||
<script src="/script/loading.js"></script>
|
||||
<script>
|
||||
// 1. 변수 선언 및 초기화
|
||||
let cardList;
|
||||
let selectedCards = [];
|
||||
let selectedColors = new Set(["All"]);
|
||||
const colorButtons = document.querySelectorAll(".color-filter-btn");
|
||||
const searchQueryInput = document.getElementById("searchQuery");
|
||||
const includeBasicCheckbox = document.getElementById("includeBasic");
|
||||
const includeAPCheckbox = document.getElementById("includeAP");
|
||||
const includeParallelCheckbox =
|
||||
document.getElementById("includeParallel");
|
||||
const includeAllTriggerRadio =
|
||||
document.getElementById("includeAllTrigger");
|
||||
const includeSpecialTriggerRadio = document.getElementById(
|
||||
"includeSpecialTrigger"
|
||||
);
|
||||
const includeColorTriggerRadio = document.getElementById(
|
||||
"includeColorTrigger"
|
||||
);
|
||||
const includeFinalTriggerRadio = document.getElementById(
|
||||
"includeFinalTrigger"
|
||||
);
|
||||
const keyCardCountElement = document.getElementById("keyCardCount");
|
||||
const colorCardCountElement = document.getElementById("colorCardCount");
|
||||
const finalCardCountElement = document.getElementById("finalCardCount");
|
||||
const specialCardCountElement =
|
||||
document.getElementById("specialCardCount");
|
||||
const totalCardCountElement = document.getElementById("totalCardCount");
|
||||
|
||||
// 2. URL 파라미터 및 로컬 스토리지 관리
|
||||
function getQueryParam(param) {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
return urlParams.get(param);
|
||||
}
|
||||
|
||||
const seriesKey = getQueryParam("series");
|
||||
const nameKey = getQueryParam("seriesName");
|
||||
|
||||
if (seriesKey) {
|
||||
localStorage.setItem(
|
||||
"selectedSeries",
|
||||
JSON.stringify({ key: seriesKey, name: nameKey })
|
||||
);
|
||||
}
|
||||
|
||||
// 3. 데이터 로딩 및 초기화
|
||||
async function loadCardData() {
|
||||
try {
|
||||
const module = await import(`./datas/${seriesKey}.js`);
|
||||
cardList = module.cardList;
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const cardsParam = urlParams.get("cards");
|
||||
|
||||
if (cardsParam) {
|
||||
const parsedCards = JSON.parse(decodeURIComponent(cardsParam));
|
||||
cardList = updateCardListFromStorage(cardList, parsedCards);
|
||||
selectedCards = parsedCards;
|
||||
displayCardList(cardList);
|
||||
updateCardList();
|
||||
} else {
|
||||
const savedSelectedCards = localStorage.getItem("selectedCards");
|
||||
if (savedSelectedCards) {
|
||||
const parsedCards = JSON.parse(
|
||||
decodeURIComponent(savedSelectedCards)
|
||||
);
|
||||
cardList = updateCardListFromStorage(cardList, parsedCards);
|
||||
selectedCards = parsedCards;
|
||||
displayCardList(cardList);
|
||||
updateCardList();
|
||||
} else {
|
||||
applyInitialFilter();
|
||||
}
|
||||
}
|
||||
|
||||
const loadingScreen = document.getElementById("loading-screen");
|
||||
if (loadingScreen) {
|
||||
loadingScreen.style.display = "none";
|
||||
}
|
||||
|
||||
updateCounters();
|
||||
} catch (error) {
|
||||
console.error("Failed to load card data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
const loadingScreen = document.getElementById("loading-screen");
|
||||
if (loadingScreen) {
|
||||
loadingScreen.style.display = "flex";
|
||||
}
|
||||
|
||||
await loadCardData();
|
||||
|
||||
const goToResultPage = document.getElementById("goToResultPage");
|
||||
if (goToResultPage) {
|
||||
goToResultPage.addEventListener("click", () => {
|
||||
const queryParams = encodeURIComponent(
|
||||
JSON.stringify(selectedCards)
|
||||
);
|
||||
const seriesKey = getQueryParam("series");
|
||||
const nameKey = getQueryParam("seriesName");
|
||||
localStorage.setItem("selectedCards", queryParams);
|
||||
localStorage.setItem(
|
||||
"selectedSeries",
|
||||
JSON.stringify({ key: seriesKey, name: nameKey })
|
||||
);
|
||||
window.location.href = `/result.html?series=${seriesKey}&seriesName=${nameKey}&cards=${queryParams}`;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function applyInitialFilter() {
|
||||
const filteredList = cardList.filter(
|
||||
(card) => card.color !== "AP" && !card.parallel
|
||||
);
|
||||
document.getElementById("includeBasic").checked = true;
|
||||
document.getElementById("includeAP").checked = false;
|
||||
document.getElementById("includeParallel").checked = false;
|
||||
displayCardList(filteredList);
|
||||
}
|
||||
|
||||
function updateCardListFromStorage(cardList, savedSelectedCards) {
|
||||
const cardMap = new Map(cardList.map((card) => [card.imgSrc, card]));
|
||||
|
||||
savedSelectedCards.forEach((savedCard) => {
|
||||
const uniqueKey = savedCard.imgSrc;
|
||||
const existingCard = cardMap.get(uniqueKey);
|
||||
if (existingCard) {
|
||||
existingCard.count = savedCard.count;
|
||||
existingCard.key = savedCard.key;
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(cardMap.values());
|
||||
}
|
||||
|
||||
const RARITY_STYLE_RULES = [
|
||||
{
|
||||
// 🌈 레인보우: 별표 포함 or UR
|
||||
match: (r) => r.includes("★") || ["UR"].includes(r),
|
||||
background:
|
||||
"linear-gradient(45deg, rgba(204, 75, 149, 0.8) 10%, rgba(102, 148, 210, 0.8), rgba(113, 194, 228, 0.8), rgba(129, 197, 101, 0.8), rgba(240, 219, 76, 0.8))",
|
||||
},
|
||||
{
|
||||
// ⚙ 메탈: SP / PcC / PcU / PcR
|
||||
match: (r) => ["SP", "PcC", "PcU", "PcR"].includes(r),
|
||||
background:
|
||||
"linear-gradient(90deg, rgba(139,155,175,0.85), rgba(231,239,247,0.9) 50%, rgba(139,155,175,0.85))",
|
||||
},
|
||||
{
|
||||
// 🟡 SR 계열
|
||||
match: (r) => ["SR", "PcSR"].includes(r),
|
||||
background: "#F2F320",
|
||||
},
|
||||
];
|
||||
|
||||
function applyRarityStyle(rarityDiv, rarity) {
|
||||
// 기본 배경
|
||||
rarityDiv.style.backgroundColor = "rgba(255, 255, 255, 0.8)";
|
||||
|
||||
for (const rule of RARITY_STYLE_RULES) {
|
||||
if (rule.match(rarity)) {
|
||||
rarityDiv.style.background = rule.background;
|
||||
break; // 첫 매칭 규칙만 적용
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 카드 목록 표시 및 업데이트
|
||||
function displayCardList(cardList) {
|
||||
const cardGrid = document.getElementById("card-grid");
|
||||
cardGrid.innerHTML = "";
|
||||
|
||||
// 광고 배너 추가
|
||||
// const totalCards = cardList.length;
|
||||
// let adCount = 0;
|
||||
// if (totalCards >= 50) {
|
||||
// adCount = Math.floor(totalCards / 150) + 1;
|
||||
// }
|
||||
// const adIndices = [];
|
||||
// if (adCount > 0) {
|
||||
// const segmentSize = Math.floor(totalCards / adCount);
|
||||
// for (let i = 0; i < adCount; i++) {
|
||||
// const start = i * segmentSize;
|
||||
// const end = (i === adCount - 1) ? totalCards - 1 : (i + 1) * segmentSize - 1;
|
||||
// const randIndex = Math.floor(Math.random() * (end - start + 1)) + start;
|
||||
// adIndices.push(randIndex);
|
||||
// }
|
||||
// }
|
||||
|
||||
cardList.forEach((card, index) => {
|
||||
const cardContainer = document.createElement("div");
|
||||
cardContainer.className =
|
||||
"cardContainer group relative z-10 hover:z-40 select-none flex flex-col";
|
||||
cardContainer.setAttribute("data-imgsrc", card.imgSrc);
|
||||
|
||||
const imgSrc = `images/${seriesKey}/${card.imgSrc.split("/").pop()}`;
|
||||
const img = document.createElement("img");
|
||||
img.src = imgSrc;
|
||||
img.alt = "";
|
||||
img.className =
|
||||
"h-full w-full object-contain object-center transition-opacity lg:h-full lg:w-full";
|
||||
img.onerror = () => handleImageError(card, img);
|
||||
|
||||
const imageContainer = document.createElement("div");
|
||||
imageContainer.className =
|
||||
"card_image cursor-pointer aspect-w-1 w-full mb-2 lg:mb-3 xl:mb-4 rounded-md lg:aspect-none";
|
||||
imageContainer.appendChild(img);
|
||||
|
||||
imageContainer.addEventListener("click", () => {
|
||||
showOverlay(card, index, cardList);
|
||||
});
|
||||
|
||||
const countDiv = document.createElement("div");
|
||||
countDiv.className = "absolute top-0 right-0";
|
||||
|
||||
const infoDiv = document.createElement("div");
|
||||
infoDiv.className = "flex justify-between";
|
||||
|
||||
if (card.rarity) {
|
||||
const rarityDiv = document.createElement("div");
|
||||
rarityDiv.className =
|
||||
"card-rarity font-bold inline-flex items-center rounded-full px-2 text-xs ring-1 ring-inset ring-gray-500/10";
|
||||
rarityDiv.textContent = card.rarity;
|
||||
|
||||
applyRarityStyle(rarityDiv, card.rarity.trim());
|
||||
|
||||
infoDiv.appendChild(rarityDiv);
|
||||
}
|
||||
|
||||
const numberDiv = document.createElement("div");
|
||||
numberDiv.className = "flex items-center text-xs";
|
||||
numberDiv.textContent =
|
||||
card.color === "AP" ? "ACTION POINT" : card.Number.slice(-5);
|
||||
infoDiv.appendChild(numberDiv);
|
||||
|
||||
const countControlDiv = document.createElement("div");
|
||||
countControlDiv.className = "pt-1 flex justify-between z-10";
|
||||
|
||||
const decrementButton = document.createElement("button");
|
||||
decrementButton.textContent = "-";
|
||||
decrementButton.className =
|
||||
"decrementButton cursor-pointer rounded-lg bg-black w-8 h-8 text-white shadow-sm hover:bg-gray-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:z-10 disabled:opacity-0 disabled:cursor-not-allowed touch-manipulation";
|
||||
if (card.count == 0) {
|
||||
decrementButton.classList.add("opacity-0", "cursor-not-allowed");
|
||||
}
|
||||
decrementButton.addEventListener("click", (event) =>
|
||||
decrementCount(card, event)
|
||||
);
|
||||
countControlDiv.appendChild(decrementButton);
|
||||
|
||||
const countSpan = document.createElement("span");
|
||||
countSpan.textContent = card.count;
|
||||
countSpan.className = "mx-1 w-8 text-center pt-1";
|
||||
countControlDiv.appendChild(countSpan);
|
||||
|
||||
const incrementButton = document.createElement("button");
|
||||
incrementButton.textContent = "+";
|
||||
incrementButton.className =
|
||||
"incrementButton cursor-pointer rounded-lg bg-black w-8 h-8 text-white shadow-sm hover:bg-gray-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:opacity-0 disabled:cursor-not-allowed touch-manipulation";
|
||||
if (card.count == 4) {
|
||||
incrementButton.classList.add("opacity-0", "cursor-not-allowed");
|
||||
}
|
||||
incrementButton.addEventListener("click", (event) =>
|
||||
incrementCount(card, event)
|
||||
);
|
||||
countControlDiv.appendChild(incrementButton);
|
||||
|
||||
const keyCardButton = document.createElement("button");
|
||||
keyCardButton.textContent = "KEY CARD";
|
||||
keyCardButton.className =
|
||||
"keyCardButton cursor-pointer rounded-lg bg-white w-full px-2 py-1 mt-1 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50";
|
||||
if (card.key) {
|
||||
keyCardButton.classList.add("opacity-100");
|
||||
keyCardButton.classList.remove("opacity-50");
|
||||
} else {
|
||||
keyCardButton.classList.add("opacity-50");
|
||||
keyCardButton.classList.remove("opacity-100");
|
||||
}
|
||||
keyCardButton.addEventListener("click", (event) =>
|
||||
toggleKeyCard(card, event)
|
||||
);
|
||||
|
||||
cardContainer.appendChild(imageContainer);
|
||||
cardContainer.appendChild(countDiv);
|
||||
cardContainer.appendChild(infoDiv);
|
||||
cardContainer.appendChild(countControlDiv);
|
||||
cardContainer.appendChild(keyCardButton);
|
||||
|
||||
cardGrid.appendChild(cardContainer);
|
||||
|
||||
// 광고 프레임
|
||||
// const adFrames = [
|
||||
// `<iframe src="https://ads-partners.coupang.com/widgets.html?id=915488&template=carousel&trackingCode=AF6561083&subId=&width=200&height=360&tsource=" class="absolute top-0 left-0 w-full h-full" frameborder="0" scrolling="no" referrerpolicy="unsafe-url" browsingtopics></iframe>`,
|
||||
// `<iframe src="https://ads-partners.coupang.com/widgets.html?id=915505&template=carousel&trackingCode=AF6561083&subId=&width=200&height=360&tsource=" class="absolute top-0 left-0 w-full h-full" frameborder="0" scrolling="no" referrerpolicy="unsafe-url" browsingtopics></iframe>`,
|
||||
// `<iframe src="https://ads-partners.coupang.com/widgets.html?id=915509&template=carousel&trackingCode=AF6561083&subId=&width=200&height=360&tsource=" class="absolute top-0 left-0 w-full h-full" frameborder="0" scrolling="no" referrerpolicy="unsafe-url" browsingtopics></iframe>`,
|
||||
// `<iframe src="https://ads-partners.coupang.com/widgets.html?id=915510&template=carousel&trackingCode=AF6561083&subId=&width=200&height=360&tsource=" class="absolute top-0 left-0 w-full h-full" frameborder="0" scrolling="no" referrerpolicy="unsafe-url" browsingtopics></iframe>`,
|
||||
// `<iframe src="https://ads-partners.coupang.com/widgets.html?id=915514&template=carousel&trackingCode=AF6561083&subId=&width=200&height=360&tsource=" class="absolute top-0 left-0 w-full h-full" frameborder="0" scrolling="no" referrerpolicy="unsafe-url" browsingtopics></iframe>`
|
||||
// ];
|
||||
|
||||
// if (adIndices.includes(index)) {
|
||||
// console.log("coupang:", index);
|
||||
|
||||
// const bannerContainer = document.createElement("div");
|
||||
// bannerContainer.className = "relative w-full h-full flex flex-col my-2";
|
||||
|
||||
// const adIndex = adIndices.indexOf(index) % adFrames.length;
|
||||
// bannerContainer.innerHTML = adFrames[adIndex];
|
||||
|
||||
// cardGrid.appendChild(bannerContainer);
|
||||
// }
|
||||
});
|
||||
|
||||
function showOverlay(card, index, cardList) {
|
||||
console.log(card, index, cardList);
|
||||
const overlay = document.getElementById("imageOverlay");
|
||||
const img = overlay.querySelector("img");
|
||||
const imgSrc = `images/${seriesKey}/${card.imgSrc.split("/").pop()}`;
|
||||
|
||||
let imageLoaded = false;
|
||||
|
||||
img.onload = () => {
|
||||
imageLoaded = true;
|
||||
};
|
||||
|
||||
img.onerror = () => {
|
||||
handleOverlayImageError(img);
|
||||
imageLoaded = true;
|
||||
};
|
||||
|
||||
img.src = imgSrc;
|
||||
overlay.style.display = "flex";
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
if (event.key === "ArrowLeft" && imageLoaded) {
|
||||
index = (index - 1 + cardList.length) % cardList.length;
|
||||
imageLoaded = false;
|
||||
showOverlay(cardList[index], index, cardList);
|
||||
event.preventDefault();
|
||||
} else if (event.key === "ArrowRight" && imageLoaded) {
|
||||
index = (index + 1) % cardList.length;
|
||||
imageLoaded = false;
|
||||
showOverlay(cardList[index], index, cardList);
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
|
||||
overlay.onclick = (event) => {
|
||||
if (event.target === overlay) {
|
||||
overlay.style.display = "none";
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function handleOverlayImageError(img) {
|
||||
img.src = "/images/uapr/comingsoon.png";
|
||||
img.onerror = null;
|
||||
}
|
||||
|
||||
const SearchResultsCounter = document.getElementById(
|
||||
"SearchResultsCounter"
|
||||
);
|
||||
SearchResultsCounter.textContent = cardList.length;
|
||||
|
||||
colorButtons.forEach((btn) => {
|
||||
const color = btn.dataset.color;
|
||||
if (selectedColors.has(color)) {
|
||||
btn.style.opacity = 1;
|
||||
} else {
|
||||
btn.style.opacity = 0.5;
|
||||
}
|
||||
|
||||
if (selectedColors.size === 0) {
|
||||
colorButtons[0].style.opacity = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleImageError(card, img) {
|
||||
img.src = "/images/uapr/comingsoon.png";
|
||||
img.onerror = null;
|
||||
}
|
||||
|
||||
// 5. 카드 개수 조절 및 키 카드 관리
|
||||
function decrementCount(card, event) {
|
||||
if (card.count > 0) {
|
||||
event.stopPropagation();
|
||||
card.count--;
|
||||
if (card.count === 0) {
|
||||
card.key = false;
|
||||
}
|
||||
updateCardDisplay(card, document.activeElement);
|
||||
updateCardCount(card, card.count);
|
||||
updateLocalStorage();
|
||||
updateQueryParameters();
|
||||
}
|
||||
}
|
||||
|
||||
function incrementCount(card, event) {
|
||||
const maxCount = card.maxCount || 4;
|
||||
|
||||
const sameNumberCards = cardList.filter(
|
||||
(c) => c.Number === card.Number
|
||||
);
|
||||
const totalCount = sameNumberCards.reduce((sum, c) => sum + c.count, 0);
|
||||
|
||||
if (totalCount < maxCount) {
|
||||
event.stopPropagation();
|
||||
card.count++;
|
||||
updateCardDisplay(card, document.activeElement);
|
||||
updateCardCount(card, card.count);
|
||||
updateLocalStorage();
|
||||
updateQueryParameters();
|
||||
}
|
||||
}
|
||||
|
||||
function updateCardDisplay(card, element) {
|
||||
const cardContainers = document.querySelectorAll(
|
||||
`.cardContainer[data-imgsrc="${card.imgSrc}"]`
|
||||
);
|
||||
let targetContainer = null;
|
||||
|
||||
cardContainers.forEach((container) => {
|
||||
targetContainer = container;
|
||||
});
|
||||
|
||||
if (targetContainer) {
|
||||
const countSpan = targetContainer.querySelector(
|
||||
"span.mx-1.w-8.text-center.pt-1"
|
||||
);
|
||||
if (countSpan) {
|
||||
countSpan.textContent = card.count;
|
||||
}
|
||||
|
||||
updateButtonState(targetContainer, card);
|
||||
}
|
||||
|
||||
updateLocalStorage();
|
||||
updateCounters();
|
||||
}
|
||||
|
||||
function updateButtonState(container, card) {
|
||||
const decrementButton = container.querySelector(
|
||||
"button.decrementButton"
|
||||
);
|
||||
const incrementButton = container.querySelector(
|
||||
"button.incrementButton"
|
||||
);
|
||||
const keyCardButton = container.querySelector("button.keyCardButton");
|
||||
|
||||
// 같은 Number를 가진 카드들의 총 개수 계산
|
||||
const sameNumberCards = cardList.filter(
|
||||
(c) => c.Number === card.Number
|
||||
);
|
||||
const totalCount = sameNumberCards.reduce((sum, c) => sum + c.count, 0);
|
||||
const maxCount = card.maxCount || 4;
|
||||
|
||||
if (decrementButton) {
|
||||
decrementButton.classList.toggle("opacity-0", card.count === 0);
|
||||
decrementButton.classList.toggle(
|
||||
"cursor-not-allowed",
|
||||
card.count === 0
|
||||
);
|
||||
}
|
||||
|
||||
if (incrementButton) {
|
||||
incrementButton.classList.toggle("opacity-0", totalCount >= maxCount);
|
||||
incrementButton.classList.toggle(
|
||||
"cursor-not-allowed",
|
||||
totalCount >= maxCount
|
||||
);
|
||||
}
|
||||
|
||||
if (keyCardButton) {
|
||||
keyCardButton.disabled = card.count === 0;
|
||||
if (card.count === 0) {
|
||||
card.key = false;
|
||||
}
|
||||
keyCardButton.classList.toggle(
|
||||
"opacity-100",
|
||||
card.key && card.count > 0
|
||||
);
|
||||
keyCardButton.classList.toggle(
|
||||
"opacity-50",
|
||||
!card.key || card.count === 0
|
||||
);
|
||||
}
|
||||
|
||||
// 같은 Number를 가진 모든 카드의 + 버튼 상태 업데이트
|
||||
sameNumberCards.forEach((sameCard) => {
|
||||
if (sameCard !== card) {
|
||||
const otherContainer = document.querySelector(
|
||||
`.cardContainer[data-imgsrc="${sameCard.imgSrc}"]`
|
||||
);
|
||||
if (otherContainer) {
|
||||
const otherIncrementButton = otherContainer.querySelector(
|
||||
"button.incrementButton"
|
||||
);
|
||||
if (otherIncrementButton) {
|
||||
otherIncrementButton.classList.toggle(
|
||||
"opacity-0",
|
||||
totalCount >= maxCount
|
||||
);
|
||||
otherIncrementButton.classList.toggle(
|
||||
"cursor-not-allowed",
|
||||
totalCount >= maxCount
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateCounters() {
|
||||
let keyCount = 0;
|
||||
let colorCount = 0;
|
||||
let finalCount = 0;
|
||||
let specialCount = 0;
|
||||
let totalCount = 0;
|
||||
|
||||
cardList.forEach((card) => {
|
||||
if (card.key && card.count > 0) {
|
||||
keyCount++;
|
||||
}
|
||||
if (card.trigger === "COLOR" && card.count > 0) {
|
||||
colorCount += card.count;
|
||||
}
|
||||
if (card.trigger === "FINAL" && card.count > 0) {
|
||||
finalCount += card.count;
|
||||
}
|
||||
if (card.trigger === "SPECIAL" && card.count > 0) {
|
||||
specialCount += card.count;
|
||||
}
|
||||
totalCount += card.count;
|
||||
});
|
||||
|
||||
keyCardCountElement.textContent = keyCount;
|
||||
colorCardCountElement.textContent = colorCount;
|
||||
finalCardCountElement.textContent = finalCount;
|
||||
specialCardCountElement.textContent = specialCount;
|
||||
totalCardCountElement.textContent = totalCount;
|
||||
}
|
||||
|
||||
function toggleKeyCard(card, event) {
|
||||
event.stopPropagation();
|
||||
|
||||
if (card.count === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const maxKeyCards = 4;
|
||||
const currentKeyCards = cardList.filter(
|
||||
(c) => c.key && c.count > 0
|
||||
).length;
|
||||
|
||||
if (card.key) {
|
||||
card.key = false;
|
||||
} else if (currentKeyCards < maxKeyCards) {
|
||||
card.key = true;
|
||||
}
|
||||
|
||||
updateCardDisplay(card, document.activeElement);
|
||||
updateLocalStorage();
|
||||
updateQueryParameters();
|
||||
}
|
||||
|
||||
function updateSelectedCards() {
|
||||
selectedCards = cardList.filter((card) => card.count > 0);
|
||||
}
|
||||
|
||||
function updateCardCount(card, count) {
|
||||
card.count = count;
|
||||
updateSelectedCards();
|
||||
updateLocalStorage();
|
||||
}
|
||||
|
||||
// 6. 로컬 스토리지 업데이트 및 결과 페이지 이동
|
||||
function updateLocalStorage() {
|
||||
const queryParams = encodeURIComponent(JSON.stringify(selectedCards));
|
||||
localStorage.setItem("selectedCards", queryParams);
|
||||
}
|
||||
|
||||
// 7. 검색 및 필터링 기능
|
||||
searchQueryInput.addEventListener("input", updateCardList);
|
||||
|
||||
colorButtons.forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
const color = button.dataset.color;
|
||||
|
||||
if (color === "All") {
|
||||
selectedColors.clear();
|
||||
selectedColors.add("All");
|
||||
} else {
|
||||
selectedColors.delete("All");
|
||||
|
||||
if (selectedColors.has(color)) {
|
||||
selectedColors.delete(color);
|
||||
} else {
|
||||
selectedColors.add(color);
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedColors.size === 0) {
|
||||
selectedColors.add("All");
|
||||
}
|
||||
|
||||
updateCardList();
|
||||
});
|
||||
});
|
||||
|
||||
function updateCardList() {
|
||||
const includeBasic = includeBasicCheckbox.checked;
|
||||
const includeAP = includeAPCheckbox.checked;
|
||||
const includeParallel = includeParallelCheckbox.checked;
|
||||
console.log(
|
||||
`TYPE FILTER - [Basic: ${includeBasic}], [AP: ${includeAP}], [Parallel: ${includeParallel}]`
|
||||
);
|
||||
|
||||
let filteredCardList = cardList;
|
||||
|
||||
filteredCardList = filteredCardList.filter((card) => {
|
||||
if (includeBasic && card.color !== "AP" && !card.parallel)
|
||||
return true;
|
||||
if (includeAP && card.color === "AP") return true;
|
||||
if (includeParallel && card.parallel) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!selectedColors.has("All")) {
|
||||
filteredCardList = filteredCardList.filter((card) => {
|
||||
if (card.color === "Multi") {
|
||||
return selectedColors.has("ALL COLOR");
|
||||
} else {
|
||||
return selectedColors.has(card.color);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const selectedTrigger = document.querySelector(
|
||||
'input[name="triggerType"]:checked'
|
||||
).value;
|
||||
switch (selectedTrigger) {
|
||||
case "specialTrigger":
|
||||
filteredCardList = filteredCardList.filter(
|
||||
(card) => card.trigger === "SPECIAL"
|
||||
);
|
||||
break;
|
||||
case "colorTrigger":
|
||||
filteredCardList = filteredCardList.filter(
|
||||
(card) => card.trigger === "COLOR"
|
||||
);
|
||||
break;
|
||||
case "finalTrigger":
|
||||
filteredCardList = filteredCardList.filter(
|
||||
(card) => card.trigger === "FINAL"
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const searchQuery = searchQueryInput.value.toLowerCase();
|
||||
if (searchQuery) {
|
||||
filteredCardList = filteredCardList.filter((card) => {
|
||||
return card.Number.toLowerCase().includes(searchQuery);
|
||||
});
|
||||
}
|
||||
|
||||
displayCardList(filteredCardList);
|
||||
}
|
||||
|
||||
includeBasicCheckbox.addEventListener("change", updateCardList);
|
||||
includeAPCheckbox.addEventListener("change", updateCardList);
|
||||
includeParallelCheckbox.addEventListener("change", updateCardList);
|
||||
|
||||
includeAllTriggerRadio.addEventListener("change", updateCardList);
|
||||
includeSpecialTriggerRadio.addEventListener("change", updateCardList);
|
||||
includeColorTriggerRadio.addEventListener("change", updateCardList);
|
||||
includeFinalTriggerRadio.addEventListener("change", updateCardList);
|
||||
|
||||
function updateQueryParameters() {
|
||||
const queryParams = encodeURIComponent(JSON.stringify(selectedCards));
|
||||
const seriesKey = getQueryParam("series");
|
||||
const nameKey = getQueryParam("seriesName");
|
||||
|
||||
const newUrl = new URL(window.location.href);
|
||||
newUrl.searchParams.set("cards", queryParams);
|
||||
window.history.replaceState({}, "", newUrl);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user