diff options
Diffstat (limited to 'static/api-docs-script.js')
-rw-r--r-- | static/api-docs-script.js | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/static/api-docs-script.js b/static/api-docs-script.js new file mode 100644 index 0000000..2f179b9 --- /dev/null +++ b/static/api-docs-script.js @@ -0,0 +1,315 @@ +// Smooth scrolling for navigation links +document.querySelectorAll('.nav-item').forEach(link => { + link.addEventListener('click', (e) => { + e.preventDefault(); + const targetId = link.getAttribute('href').substring(1); + const targetElement = document.getElementById(targetId); + + if (targetElement) { + targetElement.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + + // Update active nav item + document.querySelectorAll('.nav-item').forEach(item => { + item.classList.remove('active'); + }); + link.classList.add('active'); + } + }); +}); + +// Copy to clipboard functionality +document.querySelectorAll('.copy-btn').forEach(button => { + button.addEventListener('click', async () => { + const textToCopy = button.getAttribute('data-copy'); + + try { + await navigator.clipboard.writeText(textToCopy); + + // Update button state + const originalText = button.textContent; + button.textContent = 'Copied!'; + button.classList.add('copied'); + + setTimeout(() => { + button.textContent = originalText; + button.classList.remove('copied'); + }, 2000); + + showToast('Copied to clipboard!', 'success'); + } catch (err) { + console.error('Failed to copy text: ', err); + showToast('Failed to copy to clipboard', 'error'); + } + }); +}); + +// Toast notification +const showToast = (message, type = 'success') => { + const toast = document.getElementById('toast'); + const toastMessage = toast.querySelector('.toast-message'); + const toastIcon = toast.querySelector('.toast-icon'); + + toastMessage.textContent = message; + + if (type === 'success') { + toast.style.background = 'var(--success)'; + toastIcon.textContent = '✓'; + } else { + toast.style.background = 'var(--error)'; + toastIcon.textContent = '✕'; + } + + toast.classList.add('show'); + + setTimeout(() => { + toast.classList.remove('show'); + }, 3000); +}; + +// Intersection Observer for active navigation +const observerOptions = { + threshold: 0.1, + rootMargin: '-100px 0px -50% 0px' +}; + +const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const id = entry.target.id; + const navLink = document.querySelector(`.nav-item[href="#${id}"]`); + + if (navLink) { + document.querySelectorAll('.nav-item').forEach(item => { + item.classList.remove('active'); + }); + navLink.classList.add('active'); + } + } + }); +}, observerOptions); + +// Observe all sections +document.querySelectorAll('.doc-section[id]').forEach(section => { + observer.observe(section); +}); + +// Navbar background on scroll +window.addEventListener('scroll', () => { + const navbar = document.querySelector('.navbar'); + if (window.scrollY > 50) { + navbar.style.background = 'rgba(255, 255, 255, 0.98)'; + } else { + navbar.style.background = 'rgba(255, 255, 255, 0.95)'; + } +}); + +// Button click handlers +document.querySelectorAll('.btn').forEach(btn => { + btn.addEventListener('click', (e) => { + const buttonText = btn.textContent.toLowerCase(); + + if (buttonText.includes('trial') || buttonText.includes('start')) { + if (!btn.closest('form')) { + e.preventDefault(); + showToast('Starting your free trial! Redirecting...', 'success'); + setTimeout(() => { + window.location.href = 'signup.html'; + }, 2000); + } + } else if (buttonText.includes('documentation') || buttonText.includes('github') || buttonText.includes('pypi')) { + e.preventDefault(); + showToast('Opening external documentation...', 'success'); + } else if (buttonText.includes('import collection')) { + e.preventDefault(); + showToast('Postman collection downloaded!', 'success'); + } + }); +}); + +// Syntax highlighting for code blocks (basic) +const highlightCode = () => { + document.querySelectorAll('pre code').forEach(block => { + let html = block.innerHTML; + + // Highlight JSON keys + html = html.replace(/"([^"]+)":/g, '<span style="color: #10b981;">"$1"</span>:'); + + // Highlight strings + html = html.replace(/: "([^"]+)"/g, ': <span style="color: #f59e0b;">"$1"</span>'); + + // Highlight numbers + html = html.replace(/: (\d+\.?\d*)/g, ': <span style="color: #3b82f6;">$1</span>'); + + // Highlight booleans + html = html.replace(/: (true|false)/g, ': <span style="color: #8b5cf6;">$1</span>'); + + // Highlight null + html = html.replace(/: (null)/g, ': <span style="color: #64748b;">$1</span>'); + + block.innerHTML = html; + }); +}; + +// Apply syntax highlighting on load +document.addEventListener('DOMContentLoaded', highlightCode); + +// Search functionality (basic) +const addSearchFunctionality = () => { + // Create search input + const searchContainer = document.createElement('div'); + searchContainer.style.cssText = ` + position: sticky; + top: 0; + background: var(--surface); + padding: 1rem 1.5rem; + border-bottom: 1px solid var(--border); + margin-bottom: 1rem; + `; + + const searchInput = document.createElement('input'); + searchInput.type = 'text'; + searchInput.placeholder = 'Search documentation...'; + searchInput.style.cssText = ` + width: 100%; + padding: 0.75rem 1rem; + border: 1px solid var(--border); + border-radius: 0.5rem; + font-size: 0.875rem; + background: white; + `; + + searchContainer.appendChild(searchInput); + + // Insert search at the top of sidebar + const sidebarContent = document.querySelector('.sidebar-content'); + sidebarContent.insertBefore(searchContainer, sidebarContent.firstChild); + + // Search functionality + searchInput.addEventListener('input', (e) => { + const query = e.target.value.toLowerCase(); + const navItems = document.querySelectorAll('.nav-item'); + + navItems.forEach(item => { + const text = item.textContent.toLowerCase(); + const section = item.closest('.nav-section'); + + if (text.includes(query)) { + item.style.display = 'block'; + section.style.display = 'block'; + } else { + item.style.display = 'none'; + } + }); + + // Hide sections with no visible items + document.querySelectorAll('.nav-section').forEach(section => { + const visibleItems = section.querySelectorAll('.nav-item[style*="block"]'); + if (visibleItems.length === 0 && query !== '') { + section.style.display = 'none'; + } else { + section.style.display = 'block'; + } + }); + }); +}; + +// Add search functionality on load +document.addEventListener('DOMContentLoaded', addSearchFunctionality); + +// Keyboard shortcuts +document.addEventListener('keydown', (e) => { + // Ctrl/Cmd + K to focus search + if ((e.ctrlKey || e.metaKey) && e.key === 'k') { + e.preventDefault(); + const searchInput = document.querySelector('input[placeholder*="Search"]'); + if (searchInput) { + searchInput.focus(); + } + } + + // Escape to clear search + if (e.key === 'Escape') { + const searchInput = document.querySelector('input[placeholder*="Search"]'); + if (searchInput && document.activeElement === searchInput) { + searchInput.value = ''; + searchInput.dispatchEvent(new Event('input')); + searchInput.blur(); + } + } +}); + +// Print styles +const addPrintStyles = () => { + const printStyles = document.createElement('style'); + printStyles.textContent = ` + @media print { + .navbar, + .sidebar, + .copy-btn, + .toast { + display: none !important; + } + + .docs-layout { + flex-direction: column; + } + + .main-content { + width: 100% !important; + } + + .content-container { + max-width: none !important; + padding: 0 !important; + } + + .code-block { + background: #f8f9fa !important; + color: #333 !important; + border: 1px solid #ddd !important; + } + + .endpoint { + break-inside: avoid; + } + } + `; + document.head.appendChild(printStyles); +}; + +addPrintStyles(); + +// Initialize everything when DOM is ready +document.addEventListener('DOMContentLoaded', () => { + // Set initial active nav item + const hash = window.location.hash; + if (hash) { + const navLink = document.querySelector(`.nav-item[href="${hash}"]`); + if (navLink) { + navLink.classList.add('active'); + } + } else { + // Default to first nav item + const firstNavItem = document.querySelector('.nav-item'); + if (firstNavItem) { + firstNavItem.classList.add('active'); + } + } +}); + +// Handle hash changes +window.addEventListener('hashchange', () => { + const hash = window.location.hash; + if (hash) { + const navLink = document.querySelector(`.nav-item[href="${hash}"]`); + if (navLink) { + document.querySelectorAll('.nav-item').forEach(item => { + item.classList.remove('active'); + }); + navLink.classList.add('active'); + } + } +}); |