// DNS Things - Theme and UI Utilities // Theme toggle functionality function initTheme() { const themeToggleBtn = document.getElementById('theme-toggle'); const lightIcon = document.getElementById('theme-toggle-light-icon'); const darkIcon = document.getElementById('theme-toggle-dark-icon'); if (!themeToggleBtn || !lightIcon || !darkIcon) return; // Check for saved theme preference or default to system preference const savedTheme = localStorage.getItem('theme'); const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; let currentTheme = savedTheme || (systemPrefersDark ? 'dark' : 'light'); // Apply initial theme if (currentTheme === 'dark') { document.documentElement.classList.add('dark'); lightIcon.classList.add('hidden'); darkIcon.classList.remove('hidden'); } else { document.documentElement.classList.remove('dark'); lightIcon.classList.remove('hidden'); darkIcon.classList.add('hidden'); } // Toggle theme function function toggleTheme() { if (document.documentElement.classList.contains('dark')) { document.documentElement.classList.remove('dark'); lightIcon.classList.remove('hidden'); darkIcon.classList.add('hidden'); localStorage.setItem('theme', 'light'); } else { document.documentElement.classList.add('dark'); lightIcon.classList.add('hidden'); darkIcon.classList.remove('hidden'); localStorage.setItem('theme', 'dark'); } } themeToggleBtn.addEventListener('click', toggleTheme); } // Tab descriptions for dynamic updates const tabDescriptions = { 'dns-lookup-tab': 'Perform DNS lookups to resolve domain names and check DNS records', 'reverse-dns-tab': 'Find domain names associated with IP addresses using reverse DNS', 'whois-tab': 'Get detailed registration and ownership information for domains and IPs', 'punycode-tab': 'Convert international domain names between Unicode and Punycode formats', 'ip-tools-tab': 'Comprehensive IP address utilities including validation, conversion, and analysis' }; // Tab switching functionality function initTabs() { const tabButtons = document.querySelectorAll('.tab-btn'); const tabContents = document.querySelectorAll('.tab-content'); const descriptionElement = document.querySelector('p.text-lg.text-gray-500.mt-2'); tabButtons.forEach(button => { button.addEventListener('click', () => { const targetTab = button.getAttribute('data-tab'); // Remove active class from all buttons and contents tabButtons.forEach(btn => { btn.classList.remove('active', 'text-indigo-600', 'dark:text-indigo-400', 'bg-white', 'dark:bg-gray-800', 'shadow'); btn.classList.add('text-gray-600', 'dark:text-gray-300', 'hover:bg-white', 'hover:dark:bg-gray-800/50'); }); tabContents.forEach(content => { content.classList.remove('active'); content.classList.add('hidden'); }); // Add active class to clicked button and show corresponding content button.classList.remove('text-gray-600', 'dark:text-gray-300', 'hover:bg-white', 'hover:dark:bg-gray-800/50'); button.classList.add('active', 'text-indigo-600', 'dark:text-indigo-400', 'bg-white', 'dark:bg-gray-800', 'shadow'); const targetContent = document.getElementById(targetTab); if (targetContent) { targetContent.classList.remove('hidden'); targetContent.classList.add('active'); } // Update description text if (descriptionElement && tabDescriptions[targetTab]) { descriptionElement.textContent = tabDescriptions[targetTab]; } }); }); // Set initial description based on active tab const activeTab = document.querySelector('.tab-btn.active'); if (activeTab && descriptionElement) { const activeTabId = activeTab.getAttribute('data-tab'); if (tabDescriptions[activeTabId]) { descriptionElement.textContent = tabDescriptions[activeTabId]; } } } // Copy to clipboard functionality function copyToClipboard(text, button) { if (navigator.clipboard && window.isSecureContext) { navigator.clipboard.writeText(text).then(() => { showCopyFeedback(button); }).catch(err => { console.error('Failed to copy: ', err); fallbackCopyTextToClipboard(text, button); }); } else { fallbackCopyTextToClipboard(text, button); } } // Make copyToClipboard globally available window.copyToClipboard = copyToClipboard; function fallbackCopyTextToClipboard(text, button) { const textArea = document.createElement('textarea'); textArea.value = text; textArea.style.position = 'fixed'; textArea.style.left = '-999999px'; textArea.style.top = '-999999px'; document.body.appendChild(textArea); textArea.focus(); textArea.select(); try { document.execCommand('copy'); showCopyFeedback(button); } catch (err) { console.error('Fallback: Oops, unable to copy', err); } document.body.removeChild(textArea); } function showCopyFeedback(button) { const originalHTML = button.innerHTML; button.innerHTML = ` `; button.classList.add('bg-green-500'); setTimeout(() => { button.innerHTML = originalHTML; button.classList.remove('bg-green-500'); }, 1000); } // Initialize copy buttons for the original HTML structure function initCopyButtons() { document.querySelectorAll('.copy-btn').forEach(button => { button.addEventListener('click', function(e) { e.preventDefault(); const targetId = this.getAttribute('data-copy-target'); const targetElement = document.getElementById(targetId); const copyIcon = this.querySelector('.copy-icon'); const copyFeedback = this.querySelector('.copy-feedback'); if (targetElement) { const textToCopy = targetElement.textContent.trim(); // Skip if text is loading or not available if (!textToCopy || textToCopy === 'loading...' || textToCopy === 'Not available') { return; } // Try to use the modern clipboard API if (navigator.clipboard && window.isSecureContext) { navigator.clipboard.writeText(textToCopy).then(() => { showCopyFeedback(copyIcon, copyFeedback); }).catch(err => { console.error('Failed to copy: ', err); fallbackCopyTextToClipboard(textToCopy, copyIcon, copyFeedback); }); } else { // Fallback for older browsers fallbackCopyTextToClipboard(textToCopy, copyIcon, copyFeedback); } } }); }); } function showCopyFeedback(copyIcon, copyFeedback) { if (copyIcon) copyIcon.classList.add('hidden'); if (copyFeedback) copyFeedback.classList.remove('hidden'); setTimeout(() => { if (copyIcon) copyIcon.classList.remove('hidden'); if (copyFeedback) copyFeedback.classList.add('hidden'); }, 2000); }