// DOM Elements const elements = { sidebar: document.getElementById('sidebar'), apiTester: document.getElementById('apiTester'), closeTester: document.getElementById('closeTester'), getApiKeyBtn: document.getElementById('getApiKeyBtn'), tryApiBtn: document.getElementById('tryApiBtn'), toast: document.getElementById('toast') }; // Navigation and scrolling const setupNavigation = () => { // 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'); } }); }); // Update active nav item on scroll const observerOptions = { rootMargin: '-100px 0px -50% 0px', threshold: 0 }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const id = entry.target.id; const navLink = document.querySelector(`[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').forEach(section => { observer.observe(section); }); }; // Code tabs functionality const setupCodeTabs = () => { document.querySelectorAll('.code-tabs').forEach(tabGroup => { const tabs = tabGroup.querySelectorAll('.tab-btn'); const codeExample = tabGroup.closest('.code-example'); const contents = codeExample.querySelectorAll('.tab-content'); tabs.forEach(tab => { tab.addEventListener('click', () => { const targetTab = tab.dataset.tab; // Update active tab tabs.forEach(t => t.classList.remove('active')); tab.classList.add('active'); // Update active content contents.forEach(content => { content.classList.remove('active'); if (content.id === targetTab) { content.classList.add('active'); } }); }); }); }); }; // Copy to clipboard functionality const setupCopyButtons = () => { document.querySelectorAll('.copy-btn').forEach(button => { button.addEventListener('click', async () => { const copyTarget = button.dataset.copy; const targetElement = document.getElementById(copyTarget); if (targetElement) { try { await navigator.clipboard.writeText(targetElement.textContent); showToast('Copied to clipboard!', 'success'); // Visual feedback const originalText = button.textContent; button.textContent = 'Copied!'; setTimeout(() => { button.textContent = originalText; }, 2000); } catch (err) { console.error('Failed to copy:', err); showToast('Failed to copy to clipboard', 'error'); } } }); }); }; // API Tester functionality const setupApiTester = () => { const tester = elements.apiTester; const closeTester = elements.closeTester; const tryApiBtn = elements.tryApiBtn; const sendRequestBtn = document.getElementById('sendRequest'); // Show API tester tryApiBtn.addEventListener('click', () => { tester.classList.add('show'); document.body.style.overflow = 'hidden'; }); // Close API tester const closeTesterModal = () => { tester.classList.remove('show'); document.body.style.overflow = 'auto'; }; closeTester.addEventListener('click', closeTesterModal); // Close on outside click tester.addEventListener('click', (e) => { if (e.target === tester) { closeTesterModal(); } }); // Close on escape key document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && tester.classList.contains('show')) { closeTesterModal(); } }); // Try It buttons for specific endpoints document.querySelectorAll('.try-it-btn').forEach(button => { button.addEventListener('click', () => { const endpoint = button.dataset.endpoint; populateApiTester(endpoint); tester.classList.add('show'); document.body.style.overflow = 'hidden'; }); }); // Send API request sendRequestBtn.addEventListener('click', async () => { await sendApiRequest(); }); }; // Populate API tester with endpoint data const populateApiTester = (endpoint) => { const methodSelect = document.getElementById('testMethod'); const endpointInput = document.getElementById('testEndpoint'); const headersTextarea = document.getElementById('testHeaders'); const bodyTextarea = document.getElementById('testBody'); const endpointConfigs = { projects: { method: 'GET', endpoint: '/projects', headers: `Authorization: Bearer your_api_key_here Content-Type: application/json`, body: '' } }; const config = endpointConfigs[endpoint]; if (config) { methodSelect.value = config.method; endpointInput.value = config.endpoint; headersTextarea.value = config.headers; bodyTextarea.value = config.body; } }; // Send API request (mock implementation) const sendApiRequest = async () => { const method = document.getElementById('testMethod').value; const endpoint = document.getElementById('testEndpoint').value; const headers = document.getElementById('testHeaders').value; const body = document.getElementById('testBody').value; const responseStatus = document.getElementById('responseStatus'); const responseBody = document.getElementById('responseBody'); // Show loading state responseStatus.textContent = 'Sending request...'; responseStatus.className = 'response-status'; responseBody.textContent = ''; try { // Parse headers const headerLines = headers.split('\n').filter(line => line.trim()); const headerObj = {}; headerLines.forEach(line => { const [key, ...valueParts] = line.split(':'); if (key && valueParts.length > 0) { headerObj[key.trim()] = valueParts.join(':').trim(); } }); // Mock API response based on endpoint const mockResponse = generateMockResponse(method, endpoint); // Simulate network delay await new Promise(resolve => setTimeout(resolve, 1000)); // Display response responseStatus.textContent = `${mockResponse.status} ${mockResponse.statusText}`; responseStatus.className = `response-status ${mockResponse.status < 400 ? 'success' : 'error'}`; responseBody.textContent = JSON.stringify(mockResponse.data, null, 2); showToast('Request completed', 'success'); } catch (error) { responseStatus.textContent = '500 Internal Server Error'; responseStatus.className = 'response-status error'; responseBody.textContent = JSON.stringify({ error: { code: 'request_failed', message: error.message || 'Failed to send request' } }, null, 2); showToast('Request failed', 'error'); } }; // Generate mock API responses const generateMockResponse = (method, endpoint) => { const responses = { 'GET /projects': { status: 200, statusText: 'OK', data: { data: [ { id: 'proj_1234567890', name: 'Website Redesign', description: 'Complete overhaul of company website', status: 'active', created_at: '2025-01-15T10:30:00Z', updated_at: '2025-01-20T14:22:00Z', owner: { id: 'user_0987654321', name: 'John Doe', email: 'john@company.com' }, team_id: 'team_1122334455', task_count: 24, completed_tasks: 12, progress: 50.0, due_date: '2025-03-01T00:00:00Z', tags: ['design', 'frontend', 'priority-high'] } ], pagination: { limit: 20, offset: 0, total: 1, has_more: false } } }, 'POST /projects': { status: 201, statusText: 'Created', data: { id: 'proj_9876543210', name: 'Mobile App Development', description: 'Build iOS and Android mobile applications', status: 'active', created_at: new Date().toISOString(), updated_at: new Date().toISOString(), owner: { id: 'user_0987654321', name: 'John Doe', email: 'john@company.com' }, team_id: 'team_1122334455', task_count: 0, completed_tasks: 0, progress: 0.0, due_date: '2025-06-01T00:00:00Z', tags: ['mobile', 'ios', 'android'] } } }; const key = `${method} ${endpoint}`; return responses[key] || { status: 404, statusText: 'Not Found', data: { error: { code: 'endpoint_not_found', message: 'The requested endpoint was not found' } } }; }; // Toast notifications const showToast = (message, type = 'success') => { const toast = elements.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'); }, 4000); }; // Get API Key functionality const setupGetApiKey = () => { elements.getApiKeyBtn.addEventListener('click', () => { showToast('Redirecting to API key management...', 'success'); setTimeout(() => { // In a real app, this would redirect to the API key management page window.location.href = 'login.html'; }, 2000); }); }; // Navbar background on scroll const setupNavbarScroll = () => { 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 const setupButtonHandlers = () => { document.querySelectorAll('.btn').forEach(btn => { btn.addEventListener('click', (e) => { const buttonText = btn.textContent.toLowerCase(); if (buttonText.includes('trial') || buttonText.includes('start')) { if (!btn.closest('.api-tester') && !btn.id) { e.preventDefault(); showToast('Starting your free trial! Redirecting...', 'success'); setTimeout(() => { window.location.href = 'signup.html'; }, 2000); } } }); }); }; // Syntax highlighting for code blocks (simple implementation) const setupSyntaxHighlighting = () => { document.querySelectorAll('pre code').forEach(block => { const text = block.textContent; // Simple JSON highlighting if (text.trim().startsWith('{') || text.trim().startsWith('[')) { try { const parsed = JSON.parse(text); const highlighted = JSON.stringify(parsed, null, 2) .replace(/"([^"]+)":/g, '"$1":') .replace(/: "([^"]+)"/g, ': "$1"') .replace(/: (\d+)/g, ': $1') .replace(/: (true|false|null)/g, ': $1'); block.innerHTML = highlighted; } catch (e) { // If JSON parsing fails, leave as is } } // Simple curl command highlighting if (text.includes('curl')) { const highlighted = text .replace(/curl/g, 'curl') .replace(/-X (GET|POST|PUT|DELETE)/g, '-X $1') .replace(/-H/g, '-H') .replace(/-d/g, '-d'); block.innerHTML = highlighted; } }); }; // Initialize everything const init = () => { setupNavigation(); setupCodeTabs(); setupCopyButtons(); setupApiTester(); setupGetApiKey(); setupNavbarScroll(); setupButtonHandlers(); setupSyntaxHighlighting(); // Set first nav item as active initially const firstNavItem = document.querySelector('.nav-item'); if (firstNavItem) { firstNavItem.classList.add('active'); } }; // Initialize when DOM is loaded if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } // Export for potential external use window.TaskFlowAPIDocs = { showToast, populateApiTester, sendApiRequest };