// FAQ Search with mobile-optimized scrolling and keyboard handling let searchTimeout = null; function handleSearchInput(event) { const query = event.target.value.trim(); if (searchTimeout) { clearTimeout(searchTimeout); } updateClearButton(); searchTimeout = setTimeout(() => { if (query.length >= 2) { searchFAQs(query); } else if (query.length === 0) { showAllFAQs(); hideResults(); } }, 300); } function handleSearchKeydown(event) { if (event.key === 'Enter') { event.preventDefault(); const query = event.target.value.trim(); // Dismiss mobile keyboard event.target.blur(); if (query.length >= 2) { // Small delay to allow keyboard to dismiss before scrolling setTimeout(() => { searchFAQs(query); }, 100); } } else if (event.key === 'Escape') { clearSearch(); event.target.blur(); } } function searchFAQs(query) { console.log('Searching for:', query); const searchTerm = query.toLowerCase(); const faqItems = document.querySelectorAll('[data-landingsite-faq-item]'); let foundItems = []; let firstMatch = null; faqItems.forEach(item => { const questionElement = item.querySelector('[data-landingsite-faq-question] h3'); const answerElement = item.querySelector('[data-landingsite-faq-answer]'); if (questionElement) { const questionText = questionElement.textContent.toLowerCase(); const answerText = answerElement ? answerElement.textContent.toLowerCase() : ''; if (questionText.includes(searchTerm) || answerText.includes(searchTerm)) { item.style.display = 'block'; item.classList.add('ring-2', 'ring-blue-400', 'bg-blue-50'); foundItems.push(item); const originalText = questionElement.textContent; questionElement.innerHTML = highlightTerm(originalText, query); if (!firstMatch) { firstMatch = item; } } else { item.style.display = 'none'; item.classList.remove('ring-2', 'ring-blue-400', 'bg-blue-50'); questionElement.textContent = questionElement.textContent.replace(/<\/?mark[^>]*>/g, ''); } } }); if (foundItems.length > 0) { showResults(foundItems.length); if (firstMatch) { // Mobile-optimized scrolling with multiple methods and longer delay scrollToElementMobile(firstMatch); } } else { showNoResults(); } } function scrollToElementMobile(element) { console.log('Mobile scrolling to element:', element); // Highlight the element immediately element.classList.add('ring-4', 'ring-green-500', 'bg-green-50'); // Multiple scroll attempts with different delays for mobile setTimeout(() => { // Method 1: scrollIntoView with different options for mobile element.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' }); }, 200); setTimeout(() => { // Method 2: Calculate position and use window.scrollTo const elementRect = element.getBoundingClientRect(); const elementTop = elementRect.top + window.pageYOffset; const headerOffset = 80; // Account for any fixed headers const targetPosition = elementTop - headerOffset; console.log('Scrolling to position:', targetPosition); window.scrollTo({ top: targetPosition, behavior: 'smooth' }); }, 400); setTimeout(() => { // Method 3: Force scroll with requestAnimationFrame for mobile compatibility const elementRect = element.getBoundingClientRect(); const elementTop = elementRect.top + window.pageYOffset; const targetPosition = elementTop - 100; // Smooth scroll animation const startPosition = window.pageYOffset; const distance = targetPosition - startPosition; const duration = 800; let start = null; function animateScroll(timestamp) { if (!start) start = timestamp; const progress = timestamp - start; const percentage = Math.min(progress / duration, 1); // Easing function const ease = percentage < 0.5 ? 2 * percentage * percentage : 1 - Math.pow(-2 * percentage + 2, 2) / 2; window.scrollTo(0, startPosition + distance * ease); if (progress < duration) { requestAnimationFrame(animateScroll); } } requestAnimationFrame(animateScroll); }, 600); // Remove highlight after longer delay for mobile setTimeout(() => { element.classList.remove('ring-4', 'ring-green-500', 'bg-green-50'); }, 4000); } function highlightTerm(text, term) { const regex = new RegExp(`(${term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'); return text.replace(regex, '$1'); } function showAllFAQs() { const faqItems = document.querySelectorAll('[data-landingsite-faq-item]'); faqItems.forEach(item => { item.style.display = 'block'; item.classList.remove('ring-2', 'ring-blue-400', 'bg-blue-50', 'ring-4', 'ring-green-500', 'bg-green-50'); const questionElement = item.querySelector('[data-landingsite-faq-question] h3'); if (questionElement) { const originalText = questionElement.textContent.replace(/<\/?mark[^>]*>/g, ''); questionElement.textContent = originalText; } }); } function showResults(count) { const resultsEl = document.getElementById('searchResults'); const countEl = document.getElementById('resultsCount'); const noResultsEl = document.getElementById('noResults'); if (resultsEl && countEl) { countEl.textContent = count; resultsEl.classList.remove('hidden'); } if (noResultsEl) { noResultsEl.classList.add('hidden'); } } function showNoResults() { const resultsEl = document.getElementById('searchResults'); const noResultsEl = document.getElementById('noResults'); if (resultsEl) { resultsEl.classList.add('hidden'); } if (noResultsEl) { noResultsEl.classList.remove('hidden'); } } function hideResults() { const resultsEl = document.getElementById('searchResults'); const noResultsEl = document.getElementById('noResults'); if (resultsEl) { resultsEl.classList.add('hidden'); } if (noResultsEl) { noResultsEl.classList.add('hidden'); } } function updateClearButton() { const searchInput = document.getElementById('faqSearch'); const clearButton = document.getElementById('clearSearch'); if (searchInput && clearButton) { if (searchInput.value.trim().length > 0) { clearButton.classList.remove('hidden'); } else { clearButton.classList.add('hidden'); } } } function clearSearch() { const searchInput = document.getElementById('faqSearch'); const clearButton = document.getElementById('clearSearch'); if (searchInput) { searchInput.value = ''; // Dismiss mobile keyboard when clearing searchInput.blur(); } if (clearButton) { clearButton.classList.add('hidden'); } showAllFAQs(); hideResults(); } // Detect if user is on mobile device function isMobileDevice() { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); } function init() { console.log('FAQ Search initialized with mobile optimization'); const searchInput = document.getElementById('faqSearch'); const clearButton = document.getElementById('clearSearch'); if (searchInput) { searchInput.addEventListener('input', handleSearchInput); searchInput.addEventListener('keydown', handleSearchKeydown); // Mobile-specific: dismiss keyboard on scroll if (isMobileDevice()) { window.addEventListener('scroll', () => { if (document.activeElement === searchInput) { searchInput.blur(); } }); // Mobile-specific: prevent zoom on focus searchInput.addEventListener('touchstart', (e) => { searchInput.style.fontSize = '16px'; }); } console.log('Search input listeners added'); } if (clearButton) { clearButton.addEventListener('click', clearSearch); console.log('Clear button listener added'); } const faqItems = document.querySelectorAll('[data-landingsite-faq-item]'); console.log('Found', faqItems.length, 'FAQ items'); if (isMobileDevice()) { console.log('Mobile device detected - enhanced scrolling enabled'); } } function teardown() { if (searchTimeout) { clearTimeout(searchTimeout); } const searchInput = document.getElementById('faqSearch'); const clearButton = document.getElementById('clearSearch'); if (searchInput) { searchInput.removeEventListener('input', handleSearchInput); searchInput.removeEventListener('keydown', handleSearchKeydown); } if (clearButton) { clearButton.removeEventListener('click', clearSearch); } // Clean up mobile-specific listeners if (isMobileDevice()) { window.removeEventListener('scroll', () => {}); } } if (typeof module !== 'undefined' && module.exports) { module.exports = { init, teardown }; } else { window.faqSearch = { init, teardown }; }