// ============================================================ // DATA // ============================================================ const annualData = [ {year:2003, sales:67478, trims:"DX, EX", colors:6, sc_est:0, fwd_pct:50, awd_pct:50, manual_pct:20, auto_pct:80, conf:"HIGH"}, {year:2004, sales:59227, trims:"DX, LX, EX", colors:6, sc_est:0, fwd_pct:48, awd_pct:52, manual_pct:18, auto_pct:82, conf:"HIGH"}, {year:2005, sales:56262, trims:"LX, EX", colors:8, sc_est:0, fwd_pct:48, awd_pct:52, manual_pct:15, auto_pct:85, conf:"HIGH"}, {year:2006, sales:51829, trims:"LX, EX, EX-P", colors:7, sc_est:0, fwd_pct:48, awd_pct:52, manual_pct:13, auto_pct:87, conf:"HIGH"}, {year:2007, sales:35218, trims:"LX, EX, EX-P, SC", colors:8, sc_est:3522, fwd_pct:52, awd_pct:48, manual_pct:12, auto_pct:88, conf:"HIGH"}, {year:2008, sales:26447, trims:"LX, EX, EX-P, SC", colors:9, sc_est:3967, fwd_pct:55, awd_pct:45, manual_pct:11, auto_pct:89, conf:"HIGH"}, {year:2009, sales:14884, trims:"LX, EX, SC", colors:8, sc_est:2530, fwd_pct:57, awd_pct:43, manual_pct:10, auto_pct:90, conf:"HIGH"}, {year:2010, sales:14247, trims:"LX, EX, SC", colors:9, sc_est:2565, fwd_pct:58, awd_pct:42, manual_pct:4, auto_pct:96, conf:"HIGH"}, {year:2011, sales:11534, trims:"LX, EX", colors:7, sc_est:0, fwd_pct:50, awd_pct:50, manual_pct:0, auto_pct:100, conf:"HIGH"}, ]; const colorData = [ {name:"Alabaster Silver Metallic", code:"NH700M", family:"Silver", years:"2006–2011", num_years:6, restriction:"All trims", rarity:"Very Common", est_total:"~130,000", desirability:"Low", hex:"#CAC9C6", sc_only:false}, {name:"Atomic Blue Metallic", code:"B537M", family:"Blue", years:"2006–2008", num_years:3, restriction:"LX, EX only", rarity:"Uncommon", est_total:"~22,000", desirability:"Moderate", hex:"#6E91AA", sc_only:false}, {name:"Cargo Khaki", code:"YR547", family:"Tan/Beige", years:"2005 only", num_years:1, restriction:"DX, LX, EX", rarity:"Rare", est_total:"~2,800", desirability:"Moderate", hex:"#8B7355", sc_only:false}, {name:"Citrus Fire Metallic", code:"YR579M", family:"Orange", years:"2009–2011", num_years:3, restriction:"LX, EX only", rarity:"Common", est_total:"~10,000", desirability:"Moderate", hex:"#C8600A", sc_only:false}, {name:"Crystal Black Pearl", code:"NH731P", family:"Black", years:"2009–2011", num_years:3, restriction:"LX, EX only", rarity:"Common", est_total:"~12,000", desirability:"High", hex:"#1E1E1C", sc_only:false}, {name:"Eternal Blue Pearl", code:"B96P", family:"Blue", years:"2003 only", num_years:1, restriction:"DX, LX, EX", rarity:"Very Rare", est_total:"~11,000", desirability:"Very High", hex:"#044996", sc_only:false}, {name:"Fiji Blue Pearl", code:"B529P", family:"Blue", years:"2004–2005", num_years:2, restriction:"DX, LX, EX", rarity:"Uncommon", est_total:"~23,000", desirability:"Moderate", hex:"#2F3964", sc_only:false}, {name:"Galapagos Green Metallic", code:"G511M", family:"Green", years:"2003–2005", num_years:3, restriction:"DX, LX, EX", rarity:"Common", est_total:"~30,000", desirability:"Very High", hex:"#99AC70", sc_only:false}, {name:"Galaxy Gray Metallic", code:"NH701M", family:"Gray", years:"2007–2008", num_years:2, restriction:"LX, EX, SC", rarity:"Uncommon", est_total:"~12,000", desirability:"Moderate", hex:"#A99D87", sc_only:false}, {name:"Kiwi Metallic", code:"GY25M", family:"Green", years:"2006–2008", num_years:3, restriction:"LX, EX only", rarity:"Uncommon", est_total:"~18,000", desirability:"Moderate", hex:"#738115", sc_only:false}, {name:"Magnesium Metallic", code:"NH675M", family:"Gray", years:"2005 only", num_years:1, restriction:"DX, LX, EX", rarity:"Rare", est_total:"~2,800", desirability:"Moderate", hex:"#8C8C8C", sc_only:false}, {name:"Midnight Red Pearl", code:"R538P", family:"Red", years:"2009–2010 SC only", num_years:2, restriction:"SC only", rarity:"Very Rare", est_total:"~1,000", desirability:"Very High", hex:"#5C1010", sc_only:true}, {name:"Nighthawk Black Pearl", code:"B92P", family:"Black", years:"2003–2008", num_years:6, restriction:"All trims", rarity:"Very Common", est_total:"~100,000", desirability:"Moderate", hex:"#0A0A0A", sc_only:false}, {name:"Omni Blue Pearl", code:"B562P", family:"Blue", years:"2009–2011", num_years:3, restriction:"LX, EX only", rarity:"Common", est_total:"~9,000", desirability:"Very High", hex:"#7B8C7A", sc_only:false}, {name:"Polished Metal Metallic", code:"NH737M", family:"Gray", years:"2009–2011", num_years:3, restriction:"LX, EX only", rarity:"Common", est_total:"~9,000", desirability:"Moderate", hex:"#615F55", sc_only:false}, {name:"Rallye Red", code:"R513", family:"Red", years:"2005–2006", num_years:2, restriction:"DX, LX, EX", rarity:"Uncommon", est_total:"~17,000", desirability:"Moderate", hex:"#9C0C0C", sc_only:false}, {name:"Root Beer Metallic", code:"YR569M", family:"Brown", years:"2007–2008 SC only", num_years:2, restriction:"SC only", rarity:"Very Rare", est_total:"~1,500", desirability:"Very High", hex:"#61481D", sc_only:true}, {name:"Royal Blue Pearl", code:"B536P", family:"Blue", years:"2008–2010", num_years:3, restriction:"SC only 2008; all 2009–10", rarity:"Rare", est_total:"~5,000", desirability:"High", hex:"#1F0F63", sc_only:false}, {name:"Satin Silver Metallic", code:"NH623M", family:"Silver", years:"2003–2005", num_years:3, restriction:"DX, LX, EX", rarity:"Common", est_total:"~30,000", desirability:"Low", hex:"#C0C0C0", sc_only:false}, {name:"Shoreline Mist Metallic", code:"YR528M", family:"Tan/Beige", years:"2003–2004", num_years:2, restriction:"DX, LX, EX", rarity:"Uncommon", est_total:"~20,000", desirability:"Low", hex:"#B8A898", sc_only:false}, {name:"Sunset Orange Pearl", code:"YR539P", family:"Orange", years:"2003–2005", num_years:3, restriction:"DX, LX, EX", rarity:"Common", est_total:"~30,000", desirability:"Very High", hex:"#D2691E", sc_only:false}, {name:"Taffeta White", code:"NH578", family:"White", years:"2010–2011", num_years:2, restriction:"LX, EX only", rarity:"Uncommon", est_total:"~5,000", desirability:"Moderate", hex:"#F1F3DB", sc_only:false}, {name:"Tango Red Pearl", code:"R525P", family:"Red", years:"2006–2011", num_years:6, restriction:"LX, EX only", rarity:"Common", est_total:"~50,000", desirability:"Moderate", hex:"#9E2222", sc_only:false}, {name:"Tangerine Metallic", code:"YR5863M", family:"Orange", years:"2006–2008", num_years:3, restriction:"LX, EX only", rarity:"Uncommon", est_total:"~18,000", desirability:"Moderate", hex:"#E07B39", sc_only:false}, ]; // ============================================================ // DATABASE RECORDS (embedded from JSON) // ============================================================ let allRecords = []; let filteredRecords = []; let currentPage = 1; const PAGE_SIZE = 50; let sortCol = "rarity_score"; let sortDir = "desc"; // Fetch the JSON data fetch("honda_element_master_data.json") .then(r => r.json()) .then(data => { allRecords = data.records; filteredRecords = [...allRecords]; populateColorFilter(); applyFilters(); renderRarityIndex(); }) .catch(() => { // Fallback: show message document.getElementById("main-tbody").innerHTML = 'Please serve this file from a local server or open honda_element_master_data.json alongside this file.'; }); // ============================================================ // ANNUAL SUMMARY // ============================================================ function renderAnnualSummary() { const maxSales = Math.max(...annualData.map(r => r.sales)); const tbody = document.getElementById("annual-tbody"); let html = ""; let totalSales = 0, totalSC = 0, totalFWD = 0, totalAWD = 0, totalManual = 0, totalAuto = 0; annualData.forEach(row => { const fwd = Math.round(row.sales * row.fwd_pct / 100); const awd = Math.round(row.sales * row.awd_pct / 100); const manual = Math.round(row.sales * row.manual_pct / 100); const auto = Math.round(row.sales * row.auto_pct / 100); const barWidth = (row.sales / maxSales * 100).toFixed(1); totalSales += row.sales; totalSC += row.sc_est; totalFWD += fwd; totalAWD += awd; totalManual += manual; totalAuto += auto; html += ` ${row.year} ${row.sales.toLocaleString()}
${row.trims} ${row.colors} ${row.sc_est > 0 ? "~" + row.sc_est.toLocaleString() : "N/A"} ~${fwd.toLocaleString()} (${row.fwd_pct}%) ~${awd.toLocaleString()} (${row.awd_pct}%) ${manual > 0 ? "~" + manual.toLocaleString() + " (" + row.manual_pct + "%)" : "None"} ~${auto.toLocaleString()} (${row.auto_pct}%) ${row.conf} `; }); // Total row html += ` TOTAL ${totalSales.toLocaleString()} ~${totalSC.toLocaleString()} ~${totalFWD.toLocaleString()} ~${totalAWD.toLocaleString()} ~${totalManual.toLocaleString()} ~${totalAuto.toLocaleString()} `; tbody.innerHTML = html; } // ============================================================ // MASTER DATABASE // ============================================================ function populateColorFilter() { const colors = [...new Set(allRecords.map(r => r.color_name))].sort(); const sel = document.getElementById("filter-color"); colors.forEach(c => { const opt = document.createElement("option"); opt.value = c; opt.textContent = c; sel.appendChild(opt); }); } function applyFilters() { const year = document.getElementById("filter-year").value; const trim = document.getElementById("filter-trim").value; const dt = document.getElementById("filter-drivetrain").value; const tx = document.getElementById("filter-transmission").value; const color = document.getElementById("filter-color").value; const rarityMin = parseInt(document.getElementById("filter-rarity-min").value) || 1; const search = document.getElementById("filter-search").value.toLowerCase(); const scColor = document.getElementById("filter-sc-color").value; filteredRecords = allRecords.filter(r => { if (year && r.year != year) return false; if (trim && r.trim !== trim) return false; if (dt && r.drivetrain !== dt) return false; if (tx && r.transmission !== tx) return false; if (color && r.color_name !== color) return false; if (r.rarity_score < rarityMin) return false; if (scColor === "yes" && !r.sc_only_color) return false; if (scColor === "no" && r.sc_only_color) return false; if (search) { const haystack = (r.color_name + r.trim + r.notes + r.color_code).toLowerCase(); if (!haystack.includes(search)) return false; } return true; }); // Sort filteredRecords.sort((a, b) => { let va = a[sortCol], vb = b[sortCol]; if (typeof va === "string") va = va.toLowerCase(); if (typeof vb === "string") vb = vb.toLowerCase(); if (va < vb) return sortDir === "asc" ? -1 : 1; if (va > vb) return sortDir === "asc" ? 1 : -1; return 0; }); currentPage = 1; document.getElementById("result-count").textContent = `Showing ${filteredRecords.length.toLocaleString()} records`; renderTable(); renderPagination(); } function sortTable(col) { if (sortCol === col) { sortDir = sortDir === "asc" ? "desc" : "asc"; } else { sortCol = col; sortDir = col === "rarity_score" || col === "estimated_production" ? "desc" : "asc"; } // Update header classes document.querySelectorAll("#main-table thead th").forEach(th => { th.classList.remove("sort-asc", "sort-desc"); if (th.dataset.col === col) { th.classList.add(sortDir === "asc" ? "sort-asc" : "sort-desc"); } }); applyFilters(); } function resetFilters() { ["filter-year","filter-trim","filter-drivetrain","filter-transmission","filter-color","filter-sc-color"].forEach(id => { document.getElementById(id).value = ""; }); document.getElementById("filter-rarity-min").value = ""; document.getElementById("filter-search").value = ""; applyFilters(); } function getRarityClass(score) { if (score <= 20) return "rarity-1-20"; if (score <= 40) return "rarity-21-40"; if (score <= 60) return "rarity-41-60"; if (score <= 80) return "rarity-61-80"; return "rarity-81-100"; } function getRarityLabel(score) { if (score <= 20) return "Common"; if (score <= 40) return "Uncommon"; if (score <= 60) return "Notable"; if (score <= 80) return "Rare"; return "Very Rare"; } const colorHexMap = {}; colorData.forEach(c => colorHexMap[c.code] = c.hex); function renderTable() { const start = (currentPage - 1) * PAGE_SIZE; const end = start + PAGE_SIZE; const pageRecords = filteredRecords.slice(start, end); const tbody = document.getElementById("main-tbody"); if (pageRecords.length === 0) { tbody.innerHTML = 'No records match the current filters.'; return; } let html = ""; pageRecords.forEach(r => { const hex = colorHexMap[r.color_code] || "#cccccc"; const tags = []; if (r.sc_only_color) tags.push('SC Color'); if (r.single_year_color) tags.push('Single Year'); if (r.transmission === "Manual") tags.push('Manual'); if (r.drivetrain === "AWD") tags.push('AWD'); html += ` ${r.year} ${r.trim} ${r.drivetrain} ${r.transmission} ${r.color_name} ${r.color_code} ${tags.join("")} ~${r.estimated_production.toLocaleString()} ${r.confidence_level} ${r.rarity_score} — ${getRarityLabel(r.rarity_score)} ${r.notes || ""} `; }); tbody.innerHTML = html; } function renderPagination() { const totalPages = Math.ceil(filteredRecords.length / PAGE_SIZE); const pag = document.getElementById("pagination"); if (totalPages <= 1) { pag.innerHTML = ""; return; } let html = ""; if (currentPage > 1) html += ``; const start = Math.max(1, currentPage - 2); const end = Math.min(totalPages, currentPage + 2); if (start > 1) { html += ``; if (start > 2) html += ``; } for (let i = start; i <= end; i++) { html += ``; } if (end < totalPages) { if (end < totalPages - 1) html += ``; html += ``; } if (currentPage < totalPages) html += ``; html += `Page ${currentPage} of ${totalPages} (${filteredRecords.length.toLocaleString()} records)`; pag.innerHTML = html; } function goPage(p) { currentPage = p; renderTable(); renderPagination(); document.getElementById("tab-database").scrollIntoView({behavior:"smooth", block:"start"}); } // ============================================================ // COLOR GUIDE // ============================================================ function renderColorGuide() { const rarityFilter = document.getElementById("color-filter-rarity").value; const familyFilter = document.getElementById("color-filter-family").value; const scFilter = document.getElementById("color-filter-sc").value; let colors = colorData.filter(c => { if (rarityFilter && c.rarity !== rarityFilter) return false; if (familyFilter && c.family !== familyFilter) return false; if (scFilter === "yes" && !c.sc_only) return false; if (scFilter === "no" && c.sc_only) return false; return true; }); const rarityOrder = {"Very Rare":0,"Rare":1,"Uncommon":2,"Common":3,"Very Common":4}; colors.sort((a,b) => rarityOrder[a.rarity] - rarityOrder[b.rarity]); const rarityBadgeClass = { "Very Rare": "rarity-81-100", "Rare": "rarity-61-80", "Uncommon": "rarity-41-60", "Common": "rarity-21-40", "Very Common": "rarity-1-20" }; const grid = document.getElementById("color-grid"); grid.innerHTML = colors.map(c => `
${c.name}
${c.code}
${c.rarity} ${c.years} ${c.family} ${c.sc_only ? 'SC Only' : ''}
Est. Total: ${c.est_total}  |  Desirability: ${c.desirability}
Restriction: ${c.restriction}
`).join(""); } // ============================================================ // RARITY INDEX // ============================================================ function renderRarityIndex() { const seen = new Set(); const top = []; const sorted = [...allRecords].sort((a,b) => b.rarity_score - a.rarity_score); for (const r of sorted) { const key = `${r.year}-${r.trim}-${r.drivetrain}-${r.transmission}-${r.color_code}`; if (!seen.has(key)) { seen.add(key); top.push(r); } if (top.length >= 50) break; } const tbody = document.getElementById("rarity-tbody"); tbody.innerHTML = top.map((r, i) => { const hex = colorHexMap[r.color_code] || "#cccccc"; const rankClass = i === 0 ? "rank-1" : i === 1 ? "rank-2" : i === 2 ? "rank-3" : ""; return ` #${i+1} ${r.year} ${r.trim} ${r.drivetrain} ${r.transmission} ${r.color_name} ~${r.estimated_production.toLocaleString()} ${r.rarity_score} `; }).join(""); } // ============================================================ // TABS // ============================================================ function showTab(name) { document.querySelectorAll(".tab-content").forEach(t => t.classList.remove("active")); document.querySelectorAll(".tab-btn").forEach(b => b.classList.remove("active")); document.getElementById("tab-" + name).classList.add("active"); event.target.classList.add("active"); } // ============================================================ // INIT // ============================================================ renderAnnualSummary(); renderColorGuide();