diff --git a/app.js b/app.js new file mode 100644 index 0000000..3c5dc63 --- /dev/null +++ b/app.js @@ -0,0 +1,80 @@ +/* filepath: /home/jonathan/git/onlyqr/app.js */ +(function() { + 'use strict'; + + // Initialize QR code generator + var qrcode = new QRCode(document.getElementById("qrcode"), { + colorDark: "#004c93" + }); + + var debounceTimer; + + function makeCode() { + var elText = document.getElementById("text"); + var elColor = document.getElementById("color"); + var text = elText.value || "https://git.0n8.de/BerriJ/onlyqr"; + + qrcode._htOption.colorDark = elColor.value; + qrcode.makeCode(text); + } + + function debouncedMakeCode() { + clearTimeout(debounceTimer); + debounceTimer = setTimeout(makeCode, 20); + } + + function downloadSVG() { + var svg = document.querySelector('#qrcode svg'); + if (!svg) { + alert('No QR code to download. Please generate a QR code first.'); + return; + } + + var svgData = new XMLSerializer().serializeToString(svg); + var svgBlob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" }); + var svgUrl = URL.createObjectURL(svgBlob); + + var downloadLink = document.createElement("a"); + downloadLink.href = svgUrl; + downloadLink.download = "qrcode.svg"; + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); + URL.revokeObjectURL(svgUrl); + } + + function initializeApp() { + // Generate initial QR code + makeCode(); + + // Focus the input field + document.getElementById("text").focus(); + + // Set up event listeners + var textInput = document.getElementById("text"); + var colorInput = document.getElementById("color"); + var downloadButton = document.getElementById("download"); + + // Text input events + textInput.addEventListener('input', debouncedMakeCode); + textInput.addEventListener('blur', makeCode); + textInput.addEventListener('keydown', function(e) { + if (e.keyCode === 13) { + makeCode(); + } + }); + + // Color input events + colorInput.addEventListener('change', makeCode); + + // Download button event + downloadButton.addEventListener('click', downloadSVG); + } + + // Initialize when DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initializeApp); + } else { + initializeApp(); + } +})(); \ No newline at end of file diff --git a/index.html b/index.html index 6ed8a2e..12d0a2c 100644 --- a/index.html +++ b/index.html @@ -5,148 +5,7 @@ QR Code Generator - - - + @@ -154,86 +13,47 @@

QR Code Generator

- + - +
- - - - + + + \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..07954ce --- /dev/null +++ b/styles.css @@ -0,0 +1,155 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 20px; +} + +.container { + background: white; + border-radius: 20px; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); + padding: 40px; + max-width: 600px; + width: 100%; + text-align: center; +} + +h1 { + color: #333; + margin-bottom: 30px; + font-size: 2.5em; + font-weight: 300; +} + +.input-group { + margin-bottom: 25px; + display: flex; + flex-wrap: wrap; + gap: 15px; + align-items: center; + justify-content: center; +} + +#text { + flex: 1; + min-width: 250px; + padding: 15px 20px; + border: 2px solid #e1e8ed; + border-radius: 25px; + font-size: 16px; + outline: none; + transition: border-color 0.3s ease; +} + +#text:focus { + border-color: #4a5568; +} + +#color { + width: 60px; + height: 50px; + border: none; + border-radius: 25px; + cursor: pointer; + outline: none; +} + +#download { + background: linear-gradient(45deg, #4a5568, #2d3748); + color: white; + border: none; + padding: 15px 25px; + border-radius: 25px; + font-size: 16px; + font-weight: 500; + cursor: pointer; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +#download:hover { + transform: translateY(-2px); + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); +} + +.qr-container { + margin: 30px 0; + display: flex; + justify-content: center; + align-items: center; + background: #f8f9fa; + border-radius: 15px; + padding: 20px; + overflow: visible; +} + +#qrcode { + display: flex; + justify-content: center; + align-items: center; +} + +#qrcode svg { + max-width: 100%; + max-height: none; + width: auto; + height: auto; + border-radius: 10px; + background: white; + padding: 10px; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + display: block; +} + +.footer { + margin-top: 20px; + color: #666; + font-size: 14px; +} + +.footer-credits { + margin-top: 10px; + font-size: 12px; + color: #999; +} + +.footer-credits a { + color: #667; + text-decoration: none; +} + +.source-link { + display: inline-flex; + align-items: center; + gap: 3px; +} + +@media (max-width: 480px) { + .container { + padding: 25px; + margin: 10px; + } + + h1 { + font-size: 2em; + margin-bottom: 20px; + } + + .input-group { + flex-direction: column; + } + + #text { + min-width: 100%; + } +} \ No newline at end of file