// 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
};