/** * Main application logic for GlitchCraft * Handles UI interactions and PWA registration */ /* global ZalgoGenerator */ // Initialize zalgo generator const zalgo = new ZalgoGenerator(); // DOM elements const inputText = document.getElementById('inputText'); const outputText = document.getElementById('outputText'); const intensitySlider = document.getElementById('intensity'); const intensityValue = document.getElementById('intensityValue'); const zalgoModeSelect = document.getElementById('zalgoMode'); const copyNotification = document.getElementById('copyNotification'); // Easter egg state let titleClickCount = 0; let titleClickTimer = null; let isWitchingHour = false; let lastShakeTime = 0; /** * Update the corrupted text output */ function updateOutput() { const text = inputText.value; let intensity = parseInt(intensitySlider.value); let mode = zalgoModeSelect.value; // Easter egg checks const easterEggTriggered = checkEasterEggs(text); // If easter egg was triggered, don't do normal generation if (easterEggTriggered) { return; } // Apply witching hour effect if (isWitchingHour) { intensity = Math.max(intensity, 8); mode = 'heavy'; } if (text) { outputText.value = zalgo.generate(text, intensity, mode); } else { outputText.value = ''; } } /** * Check for easter eggs in the input text */ function checkEasterEggs(text) { const lowerText = text.toLowerCase().trim(); // "He Comes" Mode if (lowerText === 'he comes' || lowerText === 'zalgo') { triggerHeComes(); return true; } // 404 Text Not Found if (lowerText === '404') { trigger404(); return true; } // Matrix Mode if (lowerText === 'red pill') { triggerMatrixRed(); return true; } if (lowerText === 'blue pill') { triggerMatrixBlue(); return true; } // Credits if (lowerText === 'credits') { triggerCredits(); return true; } return false; } /** * Copy text to clipboard and show notification */ async function copyToClipboard() { if (!outputText.value) return; try { await navigator.clipboard.writeText(outputText.value); // Show copy notification copyNotification.classList.add('show'); setTimeout(() => { copyNotification.classList.remove('show'); }, 2000); } catch (err) { // Fallback for older browsers outputText.select(); document.execCommand('copy'); // Show copy notification copyNotification.classList.add('show'); setTimeout(() => { copyNotification.classList.remove('show'); }, 2000); } } /** * Easter Egg Functions */ // "He Comes" Mode function triggerHeComes() { zalgoModeSelect.value = 'heavy'; intensitySlider.value = 10; intensityValue.textContent = '10'; // Flash effect document.body.style.backgroundColor = '#330000'; setTimeout(() => { document.body.style.backgroundColor = ''; }, 200); // Update output after mode change setTimeout(() => { outputText.value = zalgo.generate(inputText.value, 10, 'heavy'); }, 100); } // 404 Text Not Found function trigger404() { outputText.value = 'T̷̢̧e̴̢̧x̷̰t̸̨̧ ̷̢̧n̴̢̧o̷̰t̸̨̧ ̷̢̧f̴̢̧o̷̰ų̸̧n̷̢̧d̴̢̧'; // Override copy notification window.tempCopyFunction = async function () { await navigator.clipboard.writeText(outputText.value); copyNotification.textContent = 'Error copied successfully!'; copyNotification.classList.add('show'); setTimeout(() => { copyNotification.classList.remove('show'); copyNotification.textContent = 'Copied!'; }, 3000); }; // Restore original after 10 seconds setTimeout(() => { window.tempCopyFunction = null; }, 10000); } // Matrix Red Pill function triggerMatrixRed() { zalgoModeSelect.value = 'heavy'; intensitySlider.value = 9; intensityValue.textContent = '9'; // Red tint effect document.documentElement.style.filter = 'hue-rotate(0deg) saturate(150%) brightness(90%)'; document.documentElement.style.background = 'linear-gradient(rgba(255,0,0,0.1), rgba(255,0,0,0.05))'; outputText.value = zalgo.generate('Welcome to the real world', 9, 'heavy'); // Clear effect after 5 seconds setTimeout(() => { document.documentElement.style.filter = ''; document.documentElement.style.background = ''; }, 5000); } // Matrix Blue Pill function triggerMatrixBlue() { zalgoModeSelect.value = 'mini'; intensitySlider.value = 1; intensityValue.textContent = '1'; // Blue calm effect document.documentElement.style.filter = 'hue-rotate(240deg) saturate(120%) brightness(110%)'; outputText.value = 'You chose... wisely'; setTimeout(() => { document.documentElement.style.filter = ''; outputText.value = zalgo.generate('Back to the ordinary world', 1, 'mini'); }, 3000); } // Developer Credits function triggerCredits() { const credits = 'Made with ❤️ and chaos by Ole-Morten Duesund'; outputText.value = zalgo.generate(credits, 7, 'full'); } // Title Click Counter for Credits function handleTitleClick() { titleClickCount++; if (titleClickTimer) { clearTimeout(titleClickTimer); } if (titleClickCount >= 10) { triggerCredits(); titleClickCount = 0; return; } // Reset counter after 3 seconds titleClickTimer = setTimeout(() => { titleClickCount = 0; }, 3000); } // Witching Hour Check (3:33 AM) function checkWitchingHour() { const now = new Date(); const hour = now.getHours(); const minute = now.getMinutes(); const isCurrentlyWitchingHour = hour === 3 && minute === 33; if (isCurrentlyWitchingHour && !isWitchingHour) { isWitchingHour = true; // Dark theme effect document.documentElement.style.filter = 'brightness(70%) contrast(120%)'; document.body.style.animation = 'subtle-shake 0.1s infinite'; // Show message const originalSubtitle = document.querySelector('.subtitle').textContent; document.querySelector('.subtitle').textContent = 'T̷̢̧h̴̢̧ḛ̷ ̸̨̧w̷̢̧i̴̢̧t̷̰c̸̨̧h̷̢̧i̴̢̧n̷̰g̸̨̧ ̷̢̧h̴̢̧o̷̰ų̸̧r̷̢̧'; // Restore after 1 minute setTimeout(() => { isWitchingHour = false; document.documentElement.style.filter = ''; document.body.style.animation = ''; document.querySelector('.subtitle').textContent = originalSubtitle; }, 60000); } else if (!isCurrentlyWitchingHour && isWitchingHour) { isWitchingHour = false; document.documentElement.style.filter = ''; document.body.style.animation = ''; } } // Mobile Shake Detection function handleDeviceMotion(event) { const acceleration = event.accelerationIncludingGravity; if (!acceleration) return; // Throttle shake detection to prevent spam const now = Date.now(); if (now - lastShakeTime < 1000) return; const shake = Math.abs(acceleration.x) + Math.abs(acceleration.y) + Math.abs(acceleration.z); if (shake > 30) { lastShakeTime = now; // Random mode and intensity const modes = ['full', 'above', 'below', 'middle', 'mini', 'heavy']; const randomMode = modes[Math.floor(Math.random() * modes.length)]; const randomIntensity = Math.floor(Math.random() * 10) + 1; zalgoModeSelect.value = randomMode; intensitySlider.value = randomIntensity; intensityValue.textContent = randomIntensity; // Haptic feedback if available if (navigator.vibrate) { navigator.vibrate(100); } // Visual feedback copyNotification.textContent = 'S̷̢̧h̴̢̧a̷̰k̸̨̧e̷̢̧n̴̢̧,̷̰ ̸̨̧n̷̢̧o̴̢̧t̷̰ ̸̨̧s̷̢̧t̴̢̧ḭ̷r̸̨̧r̷̢̧e̴̢̧d̷̰'; copyNotification.classList.add('show'); setTimeout(() => { copyNotification.classList.remove('show'); copyNotification.textContent = 'Copied!'; }, 2000); updateOutput(); } } // Event listeners inputText.addEventListener('input', updateOutput); intensitySlider.addEventListener('input', () => { intensityValue.textContent = intensitySlider.value; updateOutput(); }); zalgoModeSelect.addEventListener('change', updateOutput); outputText.addEventListener('click', () => { // Check for custom copy function (404 easter egg) if (window.tempCopyFunction) { window.tempCopyFunction(); } else { copyToClipboard(); } }); // Handle keyboard shortcuts document.addEventListener('keydown', e => { // Ctrl/Cmd + C when output is focused to copy if ((e.ctrlKey || e.metaKey) && e.key === 'c' && document.activeElement === outputText) { copyToClipboard(); } }); // Register service worker for PWA functionality if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker .register('sw.js') .then(registration => { console.log('Service Worker registered successfully:', registration.scope); }) .catch(error => { console.log('Service Worker registration failed:', error); }); }); } // Handle install prompt for PWA window.addEventListener('beforeinstallprompt', e => { // Prevent the mini-infobar from appearing on mobile e.preventDefault(); // Store the event so it can be triggered later if needed // Currently not used but kept for potential future install button window.deferredPrompt = e; console.log('Install prompt ready'); }); // Focus input on load window.addEventListener('load', () => { inputText.focus(); // Set up easter egg event listeners setupEasterEggs(); }); // Easter Egg Setup function setupEasterEggs() { // Title click for credits const title = document.querySelector('h1'); title.addEventListener('click', handleTitleClick); title.style.cursor = 'pointer'; // Witching hour check every minute setInterval(checkWitchingHour, 60000); checkWitchingHour(); // Initial check // Mobile shake detection if (window.DeviceMotionEvent) { window.addEventListener('devicemotion', handleDeviceMotion); } // Request device motion permission on iOS 13+ if (typeof DeviceMotionEvent.requestPermission === 'function') { // We'll request permission on first user interaction document.addEventListener('touchstart', requestMotionPermission, { once: true }); } } // Request motion permission for iOS function requestMotionPermission() { if (typeof DeviceMotionEvent.requestPermission === 'function') { DeviceMotionEvent.requestPermission() .then(permissionState => { if (permissionState === 'granted') { window.addEventListener('devicemotion', handleDeviceMotion); } }) .catch(console.error); } }