Spaces:
Sleeping
Sleeping
| // Wait for DOM to be fully loaded | |
| document.addEventListener('DOMContentLoaded', function () { | |
| // State | |
| let noClickCount = 0; | |
| let yesButtonScale = 1; | |
| // Creative messages when clicking "No" | |
| const noMessages = [ | |
| "Are you sure? π₯Ί", | |
| "Really? Think again! π", | |
| "But... but... π’", | |
| "You're breaking my heart! π", | |
| "Please reconsider? π", | |
| "I'll give you chocolate! π«", | |
| "What if I say pretty please? π₯Ή", | |
| "The Yes button is getting bigger... notice? π", | |
| "I'll be sad forever... π", | |
| "Just one chance? π―", | |
| "I promise to be awesome! β", | |
| "You're making the teddy bear cry! π§Έπ§", | |
| "Even the flowers are wilting... ππ", | |
| "My heart is doing backflips of sadness! π€ΈββοΈπ", | |
| "The universe wants you to say yes! π", | |
| "I'll write you poetry! πβ¨", | |
| "I'll serenade you! π΅π€", | |
| "Fine, I'll do the dishes for a month! π½οΈ", | |
| "I'll let you pick all the movies! π¬", | |
| "Okay seriously, just click Yes already! π€", | |
| "The No button is getting tired... π΄", | |
| "Even my grandma thinks you should say yes! π΅", | |
| "I'll give you my Netflix password! πΊ", | |
| "The stars are aligning for a YES! ββ¨", | |
| "This is your sign to click YES! πͺ§", | |
| "I'll buy you pizza! π", | |
| "Come on, you know you want to! π", | |
| "The Yes button misses you! π", | |
| "I'll teach you my secret cookie recipe! πͺ", | |
| "Fine, you can have the last slice! π°", | |
| "I'm running out of creative messages... π ", | |
| "Seriously though... please? π₯Ίππ", | |
| "The No button doesn't even work anymore! π«", | |
| "You've unlocked: Persistent Mode! π", | |
| "I'll never give up! Never! πͺ", | |
| "This is like the 100th no... just say yes! π―", | |
| "The teddy bear is packing its bags... π§³π§Έ", | |
| "Okay, you win... JK! Keep trying! π", | |
| "Plot twist: There is no No button! π", | |
| "You're really testing my patience here! β°", | |
| "The Yes button is HUGE now! How can you resist? π―", | |
| "I'll name a star after you! β", | |
| "Fine, I'll do your laundry too! π", | |
| "This is getting ridiculous... just say yes! π€¦", | |
| "The No button is having an existential crisis! π€", | |
| "Even the code is begging you to click Yes! π»", | |
| "I'll give you unlimited hugs! π€", | |
| "The universe is literally expanding the Yes button! π", | |
| "You're more stubborn than a mule! π΄", | |
| "Okay fine, you can have my fries! π" | |
| ]; | |
| // DOM Elements | |
| const yesBtn = document.getElementById('yesBtn'); | |
| const noBtn = document.getElementById('noBtn'); | |
| const phrase = document.getElementById('phrase'); | |
| const questionScreen = document.getElementById('questionScreen'); | |
| const successScreen = document.getElementById('successScreen'); | |
| const attemptCounter = document.getElementById('attemptCounter'); | |
| const replayBtn = document.getElementById('replayBtn'); | |
| const statsMessage = document.getElementById('statsMessage'); | |
| const copyBtn = document.getElementById('copyBtn'); | |
| const shareUrl = document.getElementById('shareUrl'); | |
| const sparkleCanvas = document.getElementById('sparkleCanvas'); | |
| // Initialize | |
| init(); | |
| function init() { | |
| // Set up canvas | |
| sparkleCanvas.width = window.innerWidth; | |
| sparkleCanvas.height = window.innerHeight; | |
| // Create floating hearts | |
| createFloatingHearts(); | |
| // Set share URL | |
| shareUrl.value = window.location.href; | |
| // Event listeners | |
| yesBtn.addEventListener('click', handleYesClick); | |
| noBtn.addEventListener('click', handleNoClick); | |
| replayBtn.addEventListener('click', resetGame); | |
| copyBtn.addEventListener('click', copyShareLink); | |
| // Sparkle effect on mouse move | |
| document.addEventListener('mousemove', createSparkle); | |
| // Resize canvas on window resize | |
| window.addEventListener('resize', () => { | |
| sparkleCanvas.width = window.innerWidth; | |
| sparkleCanvas.height = window.innerHeight; | |
| }); | |
| } | |
| function handleYesClick() { | |
| // Play celebration sound | |
| playCelebrationSound(); | |
| // Add explosion effect on button | |
| createButtonExplosion(yesBtn); | |
| // Screen shake effect | |
| document.body.classList.add('screen-shake'); | |
| setTimeout(() => document.body.classList.remove('screen-shake'), 500); | |
| // Hide question screen | |
| questionScreen.classList.remove('active'); | |
| // Show success screen with animation | |
| setTimeout(() => { | |
| successScreen.classList.add('active'); | |
| createConfetti(); | |
| createFireworks(); | |
| createHeartExplosion(); | |
| // Show stats | |
| if (noClickCount > 0) { | |
| statsMessage.textContent = `It took ${noClickCount} "No" click${noClickCount > 1 ? 's' : ''} before you said yes! π`; | |
| } else { | |
| statsMessage.textContent = "You said yes right away! You're amazing! π"; | |
| } | |
| }, 300); | |
| } | |
| function handleNoClick() { | |
| noClickCount++; | |
| // Update counter | |
| attemptCounter.textContent = `No clicks: ${noClickCount}`; | |
| // Show message | |
| const messageIndex = Math.min(noClickCount - 1, noMessages.length - 1); | |
| phrase.textContent = noMessages[messageIndex]; | |
| phrase.classList.add('shake'); | |
| setTimeout(() => phrase.classList.remove('shake'), 500); | |
| // Make Yes button bigger | |
| yesButtonScale += 0.1; | |
| yesBtn.style.transform = `scale(${yesButtonScale})`; | |
| // Make No button smaller and move it | |
| const newSize = Math.max(0.5, 1 - (noClickCount * 0.05)); | |
| noBtn.style.transform = `scale(${newSize})`; | |
| // Move No button to random position after 5 clicks | |
| if (noClickCount >= 5) { | |
| moveNoButton(); | |
| } | |
| // Make No button harder to click after 10 clicks | |
| if (noClickCount >= 10) { | |
| noBtn.addEventListener('mouseenter', dodgeButton); | |
| } | |
| } | |
| function moveNoButton() { | |
| const container = document.querySelector('.button-container'); | |
| const containerRect = container.getBoundingClientRect(); | |
| const btnRect = noBtn.getBoundingClientRect(); | |
| const maxX = containerRect.width - btnRect.width; | |
| const maxY = containerRect.height - btnRect.height; | |
| const randomX = Math.random() * maxX; | |
| const randomY = Math.random() * maxY; | |
| noBtn.style.position = 'absolute'; | |
| noBtn.style.left = `${randomX}px`; | |
| noBtn.style.top = `${randomY}px`; | |
| } | |
| function dodgeButton() { | |
| const container = document.querySelector('.button-container'); | |
| const containerRect = container.getBoundingClientRect(); | |
| const randomX = Math.random() * (containerRect.width - 100); | |
| const randomY = Math.random() * (containerRect.height - 50); | |
| noBtn.style.left = `${randomX}px`; | |
| noBtn.style.top = `${randomY}px`; | |
| } | |
| function resetGame() { | |
| noClickCount = 0; | |
| yesButtonScale = 1; | |
| // Reset UI | |
| phrase.textContent = ''; | |
| attemptCounter.textContent = ''; | |
| yesBtn.style.transform = 'scale(1)'; | |
| noBtn.style.transform = 'scale(1)'; | |
| noBtn.style.position = 'relative'; | |
| noBtn.style.left = 'auto'; | |
| noBtn.style.top = 'auto'; | |
| noBtn.removeEventListener('mouseenter', dodgeButton); | |
| // Switch screens | |
| successScreen.classList.remove('active'); | |
| setTimeout(() => { | |
| questionScreen.classList.add('active'); | |
| }, 300); | |
| } | |
| function createFloatingHearts() { | |
| const heartsBackground = document.getElementById('heartsBackground'); | |
| const heartEmojis = ['π', 'π', 'π', 'π', 'π', 'β€οΈ', 'π§‘', 'π', 'π', 'π', 'π']; | |
| for (let i = 0; i < 15; i++) { | |
| const heart = document.createElement('div'); | |
| heart.className = 'floating-heart'; | |
| heart.textContent = heartEmojis[Math.floor(Math.random() * heartEmojis.length)]; | |
| heart.style.left = `${Math.random() * 100}%`; | |
| heart.style.animationDuration = `${10 + Math.random() * 10}s`; | |
| heart.style.animationDelay = `${Math.random() * 5}s`; | |
| heart.style.fontSize = `${20 + Math.random() * 20}px`; | |
| heartsBackground.appendChild(heart); | |
| } | |
| } | |
| function createSparkle(e) { | |
| const ctx = sparkleCanvas.getContext('2d'); | |
| const x = e.clientX; | |
| const y = e.clientY; | |
| // Random sparkle properties | |
| const size = Math.random() * 3 + 1; | |
| const life = 30; | |
| drawSparkle(ctx, x, y, size, life); | |
| } | |
| function drawSparkle(ctx, x, y, size, life) { | |
| if (life <= 0) return; | |
| ctx.fillStyle = `rgba(255, ${100 + life * 5}, ${150 + life * 3}, ${life / 30})`; | |
| ctx.beginPath(); | |
| ctx.arc(x, y, size, 0, Math.PI * 2); | |
| ctx.fill(); | |
| setTimeout(() => { | |
| ctx.clearRect(x - size - 1, y - size - 1, size * 2 + 2, size * 2 + 2); | |
| drawSparkle(ctx, x, y, size, life - 1); | |
| }, 50); | |
| } | |
| function createConfetti() { | |
| const duration = 3000; | |
| const animationEnd = Date.now() + duration; | |
| const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff']; | |
| const confettiInterval = setInterval(() => { | |
| const timeLeft = animationEnd - Date.now(); | |
| if (timeLeft <= 0) { | |
| clearInterval(confettiInterval); | |
| return; | |
| } | |
| const particleCount = 3; | |
| for (let i = 0; i < particleCount; i++) { | |
| const particle = document.createElement('div'); | |
| particle.className = 'confetti'; | |
| particle.style.left = `${Math.random() * 100}%`; | |
| particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; | |
| particle.style.animationDuration = `${Math.random() * 2 + 1}s`; | |
| document.body.appendChild(particle); | |
| setTimeout(() => particle.remove(), 3000); | |
| } | |
| }, 50); | |
| } | |
| function copyShareLink() { | |
| shareUrl.select(); | |
| shareUrl.setSelectionRange(0, 99999); // For mobile devices | |
| navigator.clipboard.writeText(shareUrl.value).then(() => { | |
| const originalText = copyBtn.textContent; | |
| copyBtn.textContent = 'Copied! β'; | |
| copyBtn.style.backgroundColor = '#10b981'; | |
| setTimeout(() => { | |
| copyBtn.textContent = originalText; | |
| copyBtn.style.backgroundColor = ''; | |
| }, 2000); | |
| }); | |
| } | |
| // Play celebration sound/song | |
| function playCelebrationSound() { | |
| try { | |
| const loveSong = document.getElementById('loveSong'); | |
| // Reset and play the song | |
| if (loveSong) { | |
| loveSong.currentTime = 0; // Start from beginning | |
| loveSong.volume = 0.7; // Set volume to 70% | |
| // Play the song | |
| const playPromise = loveSong.play(); | |
| if (playPromise !== undefined) { | |
| playPromise | |
| .then(() => { | |
| console.log('Love song playing!'); | |
| }) | |
| .catch(error => { | |
| console.log('Auto-play prevented:', error); | |
| // Fallback to simple tones if song can't play | |
| playFallbackTones(); | |
| }); | |
| } | |
| } else { | |
| // Fallback if audio element not found | |
| playFallbackTones(); | |
| } | |
| } catch (e) { | |
| console.log('Audio error:', e); | |
| playFallbackTones(); | |
| } | |
| } | |
| // Fallback function for simple tones (if song fails to play) | |
| function playFallbackTones() { | |
| try { | |
| const audioContext = new (window.AudioContext || window.webkitAudioContext)(); | |
| // Create a series of happy notes | |
| const notes = [523.25, 659.25, 783.99, 1046.50]; // C5, E5, G5, C6 | |
| notes.forEach((frequency, index) => { | |
| const oscillator = audioContext.createOscillator(); | |
| const gainNode = audioContext.createGain(); | |
| oscillator.connect(gainNode); | |
| gainNode.connect(audioContext.destination); | |
| oscillator.frequency.value = frequency; | |
| oscillator.type = 'sine'; | |
| const startTime = audioContext.currentTime + (index * 0.1); | |
| const duration = 0.3; | |
| gainNode.gain.setValueAtTime(0.3, startTime); | |
| gainNode.gain.exponentialRampToValueAtTime(0.01, startTime + duration); | |
| oscillator.start(startTime); | |
| oscillator.stop(startTime + duration); | |
| }); | |
| } catch (e) { | |
| console.log('Fallback audio not supported'); | |
| } | |
| } | |
| // Create button explosion effect | |
| function createButtonExplosion(button) { | |
| const rect = button.getBoundingClientRect(); | |
| const centerX = rect.left + rect.width / 2; | |
| const centerY = rect.top + rect.height / 2; | |
| for (let i = 0; i < 20; i++) { | |
| const particle = document.createElement('div'); | |
| particle.className = 'explosion-particle'; | |
| particle.style.left = centerX + 'px'; | |
| particle.style.top = centerY + 'px'; | |
| const angle = (Math.PI * 2 * i) / 20; | |
| const velocity = 100 + Math.random() * 100; | |
| const tx = Math.cos(angle) * velocity; | |
| const ty = Math.sin(angle) * velocity; | |
| particle.style.setProperty('--tx', tx + 'px'); | |
| particle.style.setProperty('--ty', ty + 'px'); | |
| document.body.appendChild(particle); | |
| setTimeout(() => particle.remove(), 1000); | |
| } | |
| } | |
| // Create fireworks effect | |
| function createFireworks() { | |
| const colors = ['#ff0000', '#ff4d6d', '#ff758f', '#ffd700', '#ff69b4', '#ff1493']; | |
| for (let i = 0; i < 5; i++) { | |
| setTimeout(() => { | |
| const x = Math.random() * window.innerWidth; | |
| const y = Math.random() * (window.innerHeight / 2); | |
| for (let j = 0; j < 30; j++) { | |
| const particle = document.createElement('div'); | |
| particle.className = 'firework-particle'; | |
| particle.style.left = x + 'px'; | |
| particle.style.top = y + 'px'; | |
| particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; | |
| const angle = (Math.PI * 2 * j) / 30; | |
| const velocity = 50 + Math.random() * 100; | |
| const tx = Math.cos(angle) * velocity; | |
| const ty = Math.sin(angle) * velocity; | |
| particle.style.setProperty('--tx', tx + 'px'); | |
| particle.style.setProperty('--ty', ty + 'px'); | |
| document.body.appendChild(particle); | |
| setTimeout(() => particle.remove(), 1500); | |
| } | |
| }, i * 300); | |
| } | |
| } | |
| // Create heart explosion effect | |
| function createHeartExplosion() { | |
| const hearts = ['π', 'π', 'π', 'π', 'π', 'β€οΈ']; | |
| for (let i = 0; i < 15; i++) { | |
| setTimeout(() => { | |
| const heart = document.createElement('div'); | |
| heart.className = 'heart-burst'; | |
| heart.textContent = hearts[Math.floor(Math.random() * hearts.length)]; | |
| heart.style.left = '50%'; | |
| heart.style.top = '50%'; | |
| heart.style.fontSize = (20 + Math.random() * 30) + 'px'; | |
| const angle = (Math.PI * 2 * i) / 15; | |
| const distance = 200 + Math.random() * 200; | |
| const tx = Math.cos(angle) * distance; | |
| const ty = Math.sin(angle) * distance; | |
| heart.style.setProperty('--tx', tx + 'px'); | |
| heart.style.setProperty('--ty', ty + 'px'); | |
| document.body.appendChild(heart); | |
| setTimeout(() => heart.remove(), 2000); | |
| }, i * 50); | |
| } | |
| } | |
| }); // End of DOMContentLoaded |