The clear button was unnecessary clutter - users can simply select and delete text in the input field if they want to clear it. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
392 lines
11 KiB
JavaScript
392 lines
11 KiB
JavaScript
/**
|
|
* 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);
|
|
}
|
|
}
|