/** * HPKIセカンド電子証明書サービス FAQ * アプリケーションロジック */ (function () { 'use strict'; // カテゴリ表示順 const CATEGORY_ORDER = ['01', '02', '03', '04', '05', '09']; // カテゴリアイコン const CATEGORY_ICONS = { '01': '1', '02': '2', '03': '3', '04': '4', '05': '5', '09': '6' }; let currentKeyword = ''; /** * FAQデータをmajorCategory → minorCategoryでグループ化 */ function groupFAQ(data) { const grouped = {}; data.forEach(function (item) { var key = item.majorCategory; if (!grouped[key]) { grouped[key] = { code: item.majorCategory, name: item.majorCategoryName, minorCategories: {} }; } var minor = item.minorCategory; if (!grouped[key].minorCategories[minor]) { grouped[key].minorCategories[minor] = []; } grouped[key].minorCategories[minor].push(item); }); return grouped; } /** * テキスト内のキーワードをハイライト */ function highlightText(text, keyword) { if (!keyword) return text; // HTMLタグ内はハイライトしない var parts = text.split(/(<[^>]+>)/); return parts.map(function (part) { if (part.startsWith('<')) return part; var escaped = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); return part.replace(new RegExp(escaped, 'gi'), '$&'); }).join(''); } /** * FAQ全体をレンダリング */ function renderFAQ(data, keyword) { var contentEl = document.getElementById('faq-content'); var grouped = groupFAQ(data); var html = ''; var totalVisible = 0; CATEGORY_ORDER.forEach(function (catCode) { var cat = grouped[catCode]; if (!cat) return; var catHtml = ''; var catHasItems = false; Object.keys(cat.minorCategories).forEach(function (minorName) { var items = cat.minorCategories[minorName]; var itemsHtml = ''; items.forEach(function (item) { var q = keyword ? highlightText(escapeHtml(item.question), keyword) : escapeHtml(item.question); var a = keyword ? highlightText(item.answer, keyword) : item.answer; itemsHtml += '
' + '' + q + '' + '
' + 'A' + a + '
' + '
'; totalVisible++; }); if (itemsHtml) { catHasItems = true; var minorTitle = keyword ? highlightText(escapeHtml(minorName), keyword) : escapeHtml(minorName); catHtml += '
' + '

' + minorTitle + '

' + itemsHtml + '
'; } }); if (catHasItems) { html += '
' + '

' + '' + CATEGORY_ICONS[catCode] + '' + cat.name + '

' + catHtml + '
'; } }); if (!html) { html = '
' + '
🔍
' + '
該当するFAQが見つかりません
' + '
別のキーワードでお試しください
' + '
'; } contentEl.innerHTML = html; // 検索件数表示 var countEl = document.getElementById('search-count'); if (keyword) { countEl.textContent = totalVisible + ' 件の結果'; } else { countEl.textContent = '全 ' + FAQ_DATA.length + ' 件'; } } /** * HTMLエスケープ(改行はスペースに変換) */ function escapeHtml(text) { var div = document.createElement('div'); div.textContent = text; return div.innerHTML.replace(/\n/g, ' '); } /** * キーワードでFAQをフィルタリング */ function filterFAQ(keyword) { currentKeyword = keyword; if (!keyword) { renderFAQ(FAQ_DATA, ''); return; } var lower = keyword.toLowerCase(); var filtered = FAQ_DATA.filter(function (item) { var answerText = item.answer.replace(/<[^>]+>/g, '').toLowerCase(); return item.question.toLowerCase().indexOf(lower) !== -1 || answerText.indexOf(lower) !== -1 || item.majorCategoryName.toLowerCase().indexOf(lower) !== -1 || item.minorCategory.toLowerCase().indexOf(lower) !== -1; }); renderFAQ(filtered, keyword); } /** * サイドバーナビゲーション生成 */ function renderNav() { var navEl = document.getElementById('category-nav'); var grouped = groupFAQ(FAQ_DATA); var html = ''; navEl.innerHTML = html; // クリックイベント(スムーススクロール) navEl.querySelectorAll('.nav-link').forEach(function (link) { link.addEventListener('click', function (e) { e.preventDefault(); var targetId = this.getAttribute('href').substring(1); var targetEl = document.getElementById(targetId); if (targetEl) { targetEl.scrollIntoView({ behavior: 'smooth', block: 'start' }); } // 検索をクリア var searchInput = document.getElementById('search-input'); if (searchInput.value) { searchInput.value = ''; filterFAQ(''); // スクロールし直す(再レンダリング後) setTimeout(function () { var el = document.getElementById(targetId); if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, 50); } }); }); } /** * 初期化 */ document.addEventListener('DOMContentLoaded', function () { renderNav(); renderFAQ(FAQ_DATA, ''); // 検索イベント var searchInput = document.getElementById('search-input'); var debounceTimer; searchInput.addEventListener('input', function () { clearTimeout(debounceTimer); var value = this.value.trim(); debounceTimer = setTimeout(function () { filterFAQ(value); }, 200); }); // Escキーで検索クリア searchInput.addEventListener('keydown', function (e) { if (e.key === 'Escape') { this.value = ''; filterFAQ(''); this.blur(); } }); }); })();