330 lines
12 KiB
JavaScript
330 lines
12 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
|
const noBtn = document.getElementById('no-btn');
|
|
const yesBtn = document.getElementById('yes-btn');
|
|
const proposalBox = document.getElementById('proposal-box');
|
|
const successBox = document.getElementById('success-message');
|
|
const lockBtn = document.getElementById('lock-btn');
|
|
const resetBtn = document.getElementById('reset-btn');
|
|
const settingsToggle = document.getElementById('settings-toggle');
|
|
const settingsPanel = document.getElementById('settings-panel');
|
|
const bgColorPicker = document.getElementById('bg-color-picker');
|
|
const popupColorPicker = document.getElementById('popup-color-picker');
|
|
const bgImageInput = document.getElementById('bg-image-input');
|
|
const removeBgBtn = document.getElementById('remove-bg-btn');
|
|
const imageRadiusPicker = document.getElementById('image-radius-picker');
|
|
const previewPage2Toggle = document.getElementById('preview-page2-toggle');
|
|
|
|
let yesScale = 1;
|
|
let isLocked = typeof IS_LOCKED !== 'undefined' ? IS_LOCKED : false;
|
|
|
|
// Audio Context for sounds
|
|
const AudioCtx = window.AudioContext || window.webkitAudioContext;
|
|
let audioCtx = null;
|
|
|
|
function playSound(type) {
|
|
if (!audioCtx) audioCtx = new AudioCtx();
|
|
const osc = audioCtx.createOscillator();
|
|
const gain = audioCtx.createGain();
|
|
|
|
osc.connect(gain);
|
|
gain.connect(audioCtx.destination);
|
|
|
|
const now = audioCtx.currentTime;
|
|
|
|
if (type === 'happy') {
|
|
// Happy sound: Arpeggio
|
|
osc.type = 'sine';
|
|
osc.frequency.setValueAtTime(523.25, now); // C5
|
|
osc.frequency.exponentialRampToValueAtTime(880, now + 0.1); // A5
|
|
gain.gain.setValueAtTime(0.3, now);
|
|
gain.gain.exponentialRampToValueAtTime(0.01, now + 0.3);
|
|
osc.start(now);
|
|
osc.stop(now + 0.3);
|
|
} else {
|
|
// Less happy sound: Low thud
|
|
osc.type = 'triangle';
|
|
osc.frequency.setValueAtTime(150, now);
|
|
osc.frequency.exponentialRampToValueAtTime(40, now + 0.2);
|
|
gain.gain.setValueAtTime(0.3, now);
|
|
gain.gain.exponentialRampToValueAtTime(0.01, now + 0.2);
|
|
osc.start(now);
|
|
osc.stop(now + 0.2);
|
|
}
|
|
}
|
|
|
|
// Settings Toggle
|
|
if (settingsToggle) {
|
|
settingsToggle.addEventListener('click', () => {
|
|
settingsPanel.style.display = settingsPanel.style.display === 'none' ? 'flex' : 'none';
|
|
});
|
|
}
|
|
|
|
// Tabs logic
|
|
const tabBtns = document.querySelectorAll('.tab-btn');
|
|
const tabContents = document.querySelectorAll('.tab-content');
|
|
tabBtns.forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
const tab = btn.dataset.tab;
|
|
tabBtns.forEach(b => b.classList.remove('active'));
|
|
tabContents.forEach(c => c.classList.remove('active'));
|
|
btn.classList.add('active');
|
|
document.getElementById(`tab-${tab}`).classList.add('active');
|
|
});
|
|
});
|
|
|
|
// Preview Page 2 Toggle
|
|
if (previewPage2Toggle) {
|
|
previewPage2Toggle.addEventListener('change', (e) => {
|
|
if (e.target.checked) {
|
|
proposalBox.style.display = 'none';
|
|
successBox.style.display = 'block';
|
|
} else {
|
|
proposalBox.style.display = 'block';
|
|
successBox.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
|
|
// Image Radius
|
|
if (imageRadiusPicker) {
|
|
imageRadiusPicker.addEventListener('input', (e) => {
|
|
document.documentElement.style.setProperty('--image-radius', `${e.target.value}px`);
|
|
});
|
|
imageRadiusPicker.addEventListener('change', (e) => {
|
|
saveSetting('image_radius', `${e.target.value}px`);
|
|
});
|
|
}
|
|
|
|
// Generic Setting Inputs
|
|
const settingInputs = document.querySelectorAll('.setting-input');
|
|
settingInputs.forEach(input => {
|
|
const key = input.dataset.key;
|
|
|
|
input.addEventListener('input', (e) => {
|
|
let value = e.target.value;
|
|
|
|
// Handle Text Updates
|
|
if (key === 'p1_title_text') {
|
|
document.querySelector('.p1-title').textContent = value;
|
|
} else if (key === 'p2_line1_text') {
|
|
document.querySelector('.p2-line1').textContent = value;
|
|
} else if (key === 'p2_line2_text') {
|
|
document.querySelector('.p2-line2').textContent = value;
|
|
} else if (key === 'p2_hint_text') {
|
|
document.querySelector('.redirect-hint').textContent = value;
|
|
}
|
|
|
|
// Handle CSS Variable Updates
|
|
let cssKey = key.replace(/_/g, '-');
|
|
if (input.type === 'range') {
|
|
if (key.includes('size')) value += 'rem';
|
|
else if (key.includes('radius')) value += 'px';
|
|
}
|
|
document.documentElement.style.setProperty(`--${cssKey}`, value);
|
|
});
|
|
|
|
input.addEventListener('change', (e) => {
|
|
let value = e.target.value;
|
|
if (input.type === 'range') {
|
|
if (key.includes('size')) value += 'rem';
|
|
else if (key.includes('radius')) value += 'px';
|
|
}
|
|
saveSetting(key, value);
|
|
});
|
|
});
|
|
|
|
function saveSetting(key, value) {
|
|
const formData = new FormData();
|
|
formData.append('action', 'update_setting');
|
|
formData.append('key', key);
|
|
formData.append('value', value);
|
|
return fetch('api/save_settings.php', { method: 'POST', body: formData });
|
|
}
|
|
|
|
// Color Pickers
|
|
if (bgColorPicker) {
|
|
bgColorPicker.addEventListener('input', (e) => {
|
|
document.documentElement.style.setProperty('--bg-color', e.target.value);
|
|
});
|
|
bgColorPicker.addEventListener('change', (e) => {
|
|
const formData = new FormData();
|
|
formData.append('action', 'update_bg_color');
|
|
formData.append('color', e.target.value);
|
|
fetch('api/save_settings.php', { method: 'POST', body: formData });
|
|
});
|
|
}
|
|
|
|
if (popupColorPicker) {
|
|
popupColorPicker.addEventListener('input', (e) => {
|
|
document.documentElement.style.setProperty('--popup-bg', e.target.value);
|
|
});
|
|
popupColorPicker.addEventListener('change', (e) => {
|
|
const formData = new FormData();
|
|
formData.append('action', 'update_popup_color');
|
|
formData.append('color', e.target.value);
|
|
fetch('api/save_settings.php', { method: 'POST', body: formData });
|
|
});
|
|
}
|
|
|
|
// Background Image Upload
|
|
if (bgImageInput) {
|
|
bgImageInput.addEventListener('change', function() {
|
|
const file = this.files[0];
|
|
if (file) {
|
|
const formData = new FormData();
|
|
formData.append('action', 'upload_bg_image');
|
|
formData.append('image', file);
|
|
|
|
fetch('api/save_settings.php', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
document.documentElement.style.setProperty('--bg-image', `url('${data.path}?t=${new Date().getTime()}')`);
|
|
location.reload(); // Reload to update the "Remove" button visibility
|
|
} else {
|
|
alert(data.error || 'Failed to upload background image');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('An error occurred during upload.');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
if (removeBgBtn) {
|
|
removeBgBtn.addEventListener('click', () => {
|
|
const formData = new FormData();
|
|
formData.append('action', 'remove_bg_image');
|
|
fetch('api/save_settings.php', { method: 'POST', body: formData })
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
document.documentElement.style.setProperty('--bg-image', 'none');
|
|
location.reload();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Lock/Unlock Toggle
|
|
lockBtn.addEventListener('click', () => {
|
|
const newLockedState = !isLocked;
|
|
const formData = new FormData();
|
|
formData.append('action', 'toggle_lock');
|
|
formData.append('lock', newLockedState);
|
|
|
|
fetch('api/save_settings.php', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
location.reload();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Reset Experience
|
|
resetBtn.addEventListener('click', () => {
|
|
if (confirm('Reset experience to page 1? (Positions and sizes will be reset)')) {
|
|
const formData = new FormData();
|
|
formData.append('action', 'reset');
|
|
|
|
fetch('api/save_settings.php', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
location.reload();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// "No" Button Dodging Logic
|
|
const dodgeThreshold = 100; // pixels
|
|
|
|
document.addEventListener('mousemove', (e) => {
|
|
if (!noBtn || (successBox && successBox.style.display === 'block') || (previewPage2Toggle && previewPage2Toggle.checked)) return;
|
|
|
|
const rect = noBtn.getBoundingClientRect();
|
|
const btnCenterX = rect.left + rect.width / 2;
|
|
const btnCenterY = rect.top + rect.height / 2;
|
|
|
|
const distance = Math.hypot(e.clientX - btnCenterX, e.clientY - btnCenterY);
|
|
|
|
if (distance < dodgeThreshold) {
|
|
const angle = Math.atan2(e.clientY - btnCenterY, e.clientX - btnCenterX);
|
|
const moveDist = dodgeThreshold - distance + 20;
|
|
|
|
let newX = rect.left - Math.cos(angle) * moveDist;
|
|
let newY = rect.top - Math.sin(angle) * moveDist;
|
|
|
|
// Keep within viewport bounds
|
|
const padding = 20;
|
|
newX = Math.max(padding, Math.min(window.innerWidth - rect.width - padding, newX));
|
|
newY = Math.max(padding, Math.min(window.innerHeight - rect.height - padding, newY));
|
|
|
|
noBtn.style.position = 'fixed';
|
|
noBtn.style.left = `${newX}px`;
|
|
noBtn.style.top = `${newY}px`;
|
|
noBtn.style.margin = '0';
|
|
}
|
|
});
|
|
|
|
// "No" Click Logic
|
|
if (noBtn) {
|
|
noBtn.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
playSound('sad');
|
|
yesScale += 0.15;
|
|
yesBtn.style.transform = `scale(${yesScale})`;
|
|
});
|
|
}
|
|
|
|
// "Yes" Click Logic
|
|
if (yesBtn) {
|
|
yesBtn.addEventListener('click', () => {
|
|
playSound('happy');
|
|
proposalBox.style.display = 'none';
|
|
successBox.style.display = 'block';
|
|
|
|
// Hide controls during celebration
|
|
document.querySelector('.admin-controls').style.display = 'none';
|
|
|
|
// Confetti effect
|
|
const duration = 15 * 1000;
|
|
const animationEnd = Date.now() + duration;
|
|
const defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 };
|
|
|
|
function randomInRange(min, max) {
|
|
return Math.random() * (max - min) + min;
|
|
}
|
|
|
|
const interval = setInterval(function() {
|
|
const timeLeft = animationEnd - Date.now();
|
|
|
|
if (timeLeft <= 0) {
|
|
return clearInterval(interval);
|
|
}
|
|
|
|
const particleCount = 50 * (timeLeft / duration);
|
|
confetti(Object.assign({}, defaults, { particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } }));
|
|
confetti(Object.assign({}, defaults, { particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } }));
|
|
}, 250);
|
|
|
|
// Redirect after 15s
|
|
setTimeout(() => {
|
|
window.location.href = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";
|
|
}, 15000);
|
|
});
|
|
}
|
|
}); |