|
1 | | -const input = document.getElementById('qr-input'); |
2 | | -const generateBtn = document.getElementById('generate-btn'); |
3 | | -const qrImg = document.getElementById('qr-img'); |
4 | | -const qrBox = document.getElementById('qr-box'); |
5 | | -const downloadBtn = document.getElementById('download-btn'); |
6 | | - |
7 | | -generateBtn.addEventListener('click', () => { |
8 | | - const value = input.value.trim(); |
9 | | - if (!value) return; |
10 | | - |
11 | | - const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=170x170&data=${encodeURIComponent( |
12 | | - value |
| 1 | +// DOM Elements |
| 2 | +const qrInput = document.querySelector('.form input'); |
| 3 | +const generateBtn = document.querySelector('.generate-btn'); |
| 4 | +const qrCode = document.querySelector('.qr-code'); |
| 5 | +const qrImg = qrCode.querySelector('img'); |
| 6 | +const downloadBtn = document.querySelector('.download-btn'); |
| 7 | +const copyBtn = document.querySelector('.copy-btn'); |
| 8 | +const footerLinks = document.querySelectorAll('.footer a'); |
| 9 | +const clickSound = new Audio('audio/audio.mp3'); |
| 10 | + |
| 11 | +// Variables |
| 12 | +let preValue = ''; |
| 13 | +let isGenerating = false; |
| 14 | + |
| 15 | +// Initialize audio settings |
| 16 | +clickSound.volume = 0.3; |
| 17 | + |
| 18 | +// Generate QR Code |
| 19 | +const generateQR = () => { |
| 20 | + const qrValue = qrInput.value.trim(); |
| 21 | + |
| 22 | + if (!qrValue || preValue === qrValue || isGenerating) return; |
| 23 | + |
| 24 | + isGenerating = true; |
| 25 | + preValue = qrValue; |
| 26 | + |
| 27 | + generateBtn.innerHTML = |
| 28 | + '<i class="fas fa-spinner fa-spin"></i> Generating...'; |
| 29 | + generateBtn.disabled = true; |
| 30 | + |
| 31 | + qrImg.src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent( |
| 32 | + qrValue |
13 | 33 | )}`; |
14 | | - qrImg.src = qrUrl; |
15 | 34 |
|
16 | 35 | qrImg.onload = () => { |
17 | | - qrBox.style.display = 'flex'; // show QR and download button |
| 36 | + qrCode.classList.add('active'); |
| 37 | + generateBtn.innerHTML = '<i class="fas fa-bolt"></i> Generate QR Code'; |
| 38 | + generateBtn.disabled = false; |
| 39 | + isGenerating = false; |
18 | 40 | }; |
19 | | -}); |
20 | 41 |
|
21 | | -downloadBtn.addEventListener('click', () => { |
22 | | - const src = qrImg.src; |
23 | | - if (!src) return; |
| 42 | + qrImg.onerror = () => { |
| 43 | + generateBtn.innerHTML = |
| 44 | + '<i class="fas fa-exclamation-circle"></i> Error! Try Again'; |
| 45 | + setTimeout(() => { |
| 46 | + generateBtn.innerHTML = '<i class="fas fa-bolt"></i> Generate QR Code'; |
| 47 | + generateBtn.disabled = false; |
| 48 | + isGenerating = false; |
| 49 | + }, 2000); |
| 50 | + }; |
| 51 | +}; |
| 52 | + |
| 53 | +// Download QR Code |
| 54 | +const downloadQR = () => { |
| 55 | + if (!qrImg.src || !qrCode.classList.contains('active')) return; |
24 | 56 |
|
25 | 57 | const link = document.createElement('a'); |
26 | | - link.href = src; |
27 | | - link.download = 'qr-code.png'; |
| 58 | + link.href = qrImg.src; |
| 59 | + link.download = `qr-code-${Date.now()}.png`; |
28 | 60 | document.body.appendChild(link); |
29 | 61 | link.click(); |
30 | 62 | document.body.removeChild(link); |
| 63 | + |
| 64 | + downloadBtn.innerHTML = '<i class="fas fa-check"></i> Downloaded!'; |
| 65 | + setTimeout(() => { |
| 66 | + downloadBtn.innerHTML = '<i class="fas fa-download"></i> Download'; |
| 67 | + }, 2000); |
| 68 | +}; |
| 69 | + |
| 70 | +// Copy QR Code to Clipboard |
| 71 | +const copyQR = async () => { |
| 72 | + if (!qrImg.src || !qrCode.classList.contains('active')) return; |
| 73 | + |
| 74 | + try { |
| 75 | + const response = await fetch(qrImg.src); |
| 76 | + const blob = await response.blob(); |
| 77 | + |
| 78 | + await navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]); |
| 79 | + |
| 80 | + copyBtn.innerHTML = '<i class="fas fa-check"></i> Copied!'; |
| 81 | + setTimeout(() => { |
| 82 | + copyBtn.innerHTML = '<i class="fas fa-copy"></i> Copy'; |
| 83 | + }, 2000); |
| 84 | + } catch (err) { |
| 85 | + copyBtn.innerHTML = '<i class="fas fa-times"></i> Failed'; |
| 86 | + setTimeout(() => { |
| 87 | + copyBtn.innerHTML = '<i class="fas fa-copy"></i> Copy'; |
| 88 | + }, 2000); |
| 89 | + } |
| 90 | +}; |
| 91 | + |
| 92 | +// Play click sound with error handling |
| 93 | +const playClickSound = () => { |
| 94 | + try { |
| 95 | + clickSound.currentTime = 0; |
| 96 | + clickSound.play().catch(e => console.log('Audio play prevented:', e)); |
| 97 | + } catch (err) { |
| 98 | + console.log('Audio error:', err); |
| 99 | + } |
| 100 | +}; |
| 101 | + |
| 102 | +// Event Listeners |
| 103 | +generateBtn.addEventListener('click', generateQR); |
| 104 | +downloadBtn.addEventListener('click', downloadQR); |
| 105 | +copyBtn.addEventListener('click', copyQR); |
| 106 | + |
| 107 | +qrInput.addEventListener('keyup', e => { |
| 108 | + if (!qrInput.value.trim()) { |
| 109 | + qrCode.classList.remove('active'); |
| 110 | + preValue = ''; |
| 111 | + } |
| 112 | + if (e.key === 'Enter') generateQR(); |
| 113 | +}); |
| 114 | + |
| 115 | +// Add sound to footer links |
| 116 | +footerLinks.forEach(link => { |
| 117 | + link.addEventListener('click', e => { |
| 118 | + if (link.getAttribute('target') === '_blank') { |
| 119 | + playClickSound(); |
| 120 | + |
| 121 | + // Delay navigation slightly to allow sound to play |
| 122 | + setTimeout(() => { |
| 123 | + window.open(link.href, '_blank'); |
| 124 | + }, 100); |
| 125 | + |
| 126 | + e.preventDefault(); |
| 127 | + } |
| 128 | + }); |
| 129 | +}); |
| 130 | + |
| 131 | +// Initialize |
| 132 | +window.addEventListener('load', () => { |
| 133 | + document.body.classList.add('animation-ready'); |
| 134 | + setTimeout(() => qrInput.focus(), 500); |
| 135 | + |
| 136 | + // Preload audio |
| 137 | + clickSound.load().catch(e => console.log('Audio preload failed:', e)); |
31 | 138 | }); |
0 commit comments