Files
QR-Code-Generator/index.html

587 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0024)https://qr.alster.space/ -->
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Just a QR Code</title>
<link rel="icon" href="data:image/svg+xml;utf8,&lt;svg xmlns=&#39;http://www.w3.org/2000/svg&#39; viewBox=&#39;0 0 32 32&#39;&gt;&lt;rect width=&#39;32&#39; height=&#39;32&#39; fill=&#39;%23ffffff&#39; rx=&#39;3&#39; ry=&#39;3&#39;/&gt;&lt;rect x=&#39;8&#39; y=&#39;8&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;12&#39; y=&#39;8&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;16&#39; y=&#39;8&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;8&#39; y=&#39;12&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;8&#39; y=&#39;16&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;20&#39; y=&#39;8&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;16&#39; y=&#39;12&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;20&#39; y=&#39;16&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;8&#39; y=&#39;20&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;12&#39; y=&#39;20&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;16&#39; y=&#39;20&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;20&#39; y=&#39;20&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;rect x=&#39;20&#39; y=&#39;12&#39; width=&#39;4&#39; height=&#39;4&#39; fill=&#39;%23000000&#39;/&gt;&lt;/svg&gt;">
<script src="./assets/qrious.min.js.Download"></script>
<!--
Licensed under the Creative Commons Attribution-NonCommercial (BY-NC) 4.0 license.
Feel free to use this for anything noncommercial.
Credit appreciated but not required.
If you don't like the news, go out and make some of your own.
-->
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.6;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f7;
color: #333;
}
h1 {
text-align: center;
margin-bottom: 30px;
color: #1d1d1f;
cursor: default;
user-select: none;
}
.container {
background-color: white;
border-radius: 10px;
padding: 30px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
position: relative;
}
.input-section {
margin-bottom: 40px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: 500;
}
input, select {
width: 100%;
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
font-size: 16px;
}
.text-input-wrapper {
position: relative;
margin-bottom: 15px;
}
.text-input-wrapper input {
padding-right: 40px;
margin-bottom: 0;
}
.clear-button {
position: absolute;
right: 0;
top: 0;
height: 100%;
width: 40px;
background: none;
border: none;
color: #666;
font-size: 18px;
cursor: pointer;
display: none;
padding: 0;
}
.clear-button:hover {
color: #333;
background: none;
}
.options-row {
display: flex;
gap: 15px;
}
.options-col {
flex: 1;
}
.color-input-wrapper {
position: relative;
}
input[type="color"] {
width: 100%;
height: 40px;
padding: 0;
border: 1px solid #ccc;
border-radius: 4px;
background-color: transparent;
cursor: pointer;
}
input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0;
}
input[type="color"]::-webkit-color-swatch {
border: none;
border-radius: 3px;
}
.output-section {
text-align: center;
margin-top: 30px;
}
#qrcode-container {
text-align: center;
}
#qrcode, #qrcode-img {
margin: 0 auto;
padding: 15px;
background-color: white;
border-radius: 4px;
display: block;
}
.download-btn {
background-color: #ff9500;
margin-top: 15px;
display: none;
}
.download-btn:hover {
background-color: #e68600;
}
.error {
color: #e74c3c;
margin-top: 5px;
}
button {
background-color: #0071e3;
color: white;
border: none;
padding: 12px 20px;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
font-weight: 500;
transition: background-color 0.2s;
width: 100%;
}
button:hover {
background-color: #0058b9;
}
.info-button {
position: absolute;
top: 20px;
right: 20px;
width: 30px;
height: 30px;
border-radius: 50%;
background: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 18px;
color: #999;
transition: color 0.2s ease;
z-index: 10;
}
.info-button:hover {
color: #333;
background: none;
}
.info-panel {
position: fixed;
top: 0;
right: -350px;
width: 330px;
height: 100%;
background-color: white;
box-shadow: -2px 0 10px rgba(0,0,0,0.1);
transition: right 0.3s ease;
z-index: 100;
overflow-y: auto;
padding: 20px;
box-sizing: border-box;
}
.info-panel.open {
right: 0;
}
.info-panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
.info-panel-header h2 {
margin: 0;
color: #333;
}
.info-close {
background: none;
border: none;
font-size: 22px;
color: #666;
cursor: pointer;
width: auto;
padding: 5px;
}
.info-close:hover {
color: #333;
background: none;
}
.info-content h3 {
font-size: 16px;
margin-top: 20px;
margin-bottom: 10px;
}
.info-content p {
font-size: 14px;
line-height: 1.6;
color: #555;
margin-bottom: 20px;
}
.footer {
margin-top: 30px;
text-align: center;
font-size: 14px;
color: #666;
}
.credit {
margin-top: 5px;
font-size: 12px;
color: #888;
}
.credit a {
text-decoration: none;
}
.credit a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<h1 id="title">Just a QR Code</h1>
<button id="info-button" class="info-button" aria-label="Information">?</button>
<div class="input-section">
<label for="text">Enter text or URL:</label>
<div class="text-input-wrapper">
<input type="text" id="text" placeholder="https://example.com" value="Gabe is cool" autofocus="">
<button type="button" id="clear-text" class="clear-button" aria-label="Clear text" style="display: block;"></button>
</div>
<div class="options-row">
<div class="options-col">
<label for="size">QR Code Size:</label>
<select id="size">
<option value="128">Small (128×128)</option>
<option value="256" selected="">Medium (256×256)</option>
<option value="512">Large (512×512)</option>
<option value="1024">X-Large (1024×1024)</option>
</select>
</div>
<div class="options-col">
<label for="errorCorrection">Error Correction:</label>
<select id="errorCorrection">
<option value="L">Low (7%)</option>
<option value="M" selected="">Medium (15%)</option>
<option value="Q">Quartile (25%)</option>
<option value="H">High (30%)</option>
</select>
</div>
</div>
<div class="options-row">
<div class="options-col">
<label for="foreground">Foreground Color:</label>
<div class="color-input-wrapper">
<input type="color" id="foreground" value="#000000">
</div>
</div>
<div class="options-col">
<label for="background">Background Color:</label>
<div class="color-input-wrapper">
<input type="color" id="background" value="#ffffff">
</div>
</div>
</div>
</div>
<div class="output-section">
<div id="qrcode-container">
<canvas id="qrcode" style="display: none;" height="256" width="256"></canvas>
<img id="qrcode-img" style="display: block;" alt="Generated QR Code" src="data:image/png;base64,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">
</div>
<div id="error-message" class="error"></div>
<button id="download" class="download-btn" style="display: inline-block;">Download QR Code</button>
</div>
</div>
<div class="info-panel" id="info-panel">
<div class="info-panel-header">
<h2>About</h2>
<button class="info-close" id="info-close"></button>
</div>
<div class="info-content">
<p>I needed to make a QR code again. It's one of those tasks that's useful enough to pop up regularly, but not frequently enough for you to have a go-to solution. When the need arises, you end up googling "QR code generator" and picking the least sketchy-looking option from the results. A couple ads and some invisible trackers are just the price you pay, right?</p>
<p>Not today.</p>
<p>Rather than bemoan the fact that there's no easy way to get just a QR code without the low-key parasitic monetization, I found a library (qrious) and put together just enough Javascript code to generate QR codes in the browser. No ads, no trackers, no sending your data to someone else's server for who-knows-what-reason.</p>
<p>Go ahead and inspect the page source. Save it to your computer, copy it, remix it, whatever you want.</p>
<p>This is my act of resistance: I'll pay for the domain name and hosting just so you and I don't ever have to give one more click or tracker data-point to some questionable "free" site again. If you find this useful, you can pay it back by making or doing something of your own and giving it away freely.</p>
<p>This is the web we were trying to build.</p>
<p>Be excellent to each other.</p>
</div>
</div>
<div class="footer">
Dieser QR-Code-Generator funktioniert vollständig in deinem Browser. Es werden keine Daten an einen Server gesendet.
<p class="credit">made with ❤️ and 🍪 by markus. self hosted on <a href="https://unraid.net" target="_blank">Unraid</a> for <a href="https://medisoftware.de" target="_blank">medisoftware</a>. credits: <a href="https://qr.alster.space/" target="_blank">alsternerd</a></p>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const textInput = document.getElementById('text');
const clearTextBtn = document.getElementById('clear-text');
const sizeSelect = document.getElementById('size');
const errorCorrectionSelect = document.getElementById('errorCorrection');
const foregroundColor = document.getElementById('foreground');
const backgroundColor = document.getElementById('background');
const downloadBtn = document.getElementById('download');
const qrcodeCanvas = document.getElementById('qrcode');
const qrcodeImg = document.getElementById('qrcode-img');
const errorMessage = document.getElementById('error-message');
const infoButton = document.getElementById('info-button');
const infoPanel = document.getElementById('info-panel');
const infoClose = document.getElementById('info-close');
const titleElement = document.getElementById('title');
// Title Easter egg
let titleClickCount = 0;
let titleTimeoutId = null;
titleElement.addEventListener('click', function() {
titleClickCount++;
clearTimeout(titleTimeoutId);
if (titleClickCount === 1) {
this.textContent = "Just a [bleep]ing QR Code";
titleTimeoutId = setTimeout(() => {
this.textContent = "Just a QR Code";
titleClickCount = 0;
}, 500);
}
});
// Info panel toggle
infoButton.addEventListener('click', function() {
infoPanel.classList.add('open');
});
infoClose.addEventListener('click', function() {
infoPanel.classList.remove('open');
});
// Close info panel when clicking outside
document.addEventListener('click', function(event) {
if (infoPanel.classList.contains('open') &&
!infoPanel.contains(event.target) &&
event.target !== infoButton) {
infoPanel.classList.remove('open');
}
});
// Close info panel with Escape key
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && infoPanel.classList.contains('open')) {
infoPanel.classList.remove('open');
}
});
// Set random compliment as default text and select it
textInput.value = 'https://medisoftware.de';
textInput.select();
// Show/hide clear button based on text input content
function toggleClearButton() {
if (textInput.value.length > 0) {
clearTextBtn.style.display = 'block';
} else {
clearTextBtn.style.display = 'none';
}
}
// Initialize clear button visibility
toggleClearButton();
// Clear text when clear button is clicked
clearTextBtn.addEventListener('click', function() {
textInput.value = '';
toggleClearButton();
textInput.focus();
generateQRCode();
});
// Update clear button visibility when text changes
textInput.addEventListener('input', function() {
toggleClearButton();
generateQRCode();
});
let qr = null;
// Generate QR code when settings change
sizeSelect.addEventListener('change', generateQRCode);
errorCorrectionSelect.addEventListener('change', generateQRCode);
foregroundColor.addEventListener('input', generateQRCode);
backgroundColor.addEventListener('input', generateQRCode);
// Download QR code as image
downloadBtn.addEventListener('click', downloadQRCode);
// Or check for URL parameters if present
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('text')) {
textInput.value = urlParams.get('text');
}
if (urlParams.has('size')) {
const sizeValue = urlParams.get('size');
if (['128', '256', '512', '1024'].includes(sizeValue)) {
sizeSelect.value = sizeValue;
}
}
if (urlParams.has('errorCorrection')) {
const ecValue = urlParams.get('errorCorrection').toUpperCase();
if (['L', 'M', 'Q', 'H'].includes(ecValue)) {
errorCorrectionSelect.value = ecValue;
}
}
if (urlParams.has('foreground')) {
const fgValue = urlParams.get('foreground');
if (/^#[0-9A-F]{6}$/i.test(fgValue)) {
foregroundColor.value = fgValue;
}
}
if (urlParams.has('background')) {
const bgValue = urlParams.get('background');
if (/^#[0-9A-F]{6}$/i.test(bgValue)) {
backgroundColor.value = bgValue;
}
}
generateQRCode();
function generateQRCode() {
const text = textInput.value.trim();
const size = parseInt(sizeSelect.value);
const errorCorrection = errorCorrectionSelect.value.toLowerCase();
const fgColor = foregroundColor.value;
const bgColor = backgroundColor.value;
// Update the gabe link color to match foreground color
const gabeLink = document.querySelector('.credit a');
if (gabeLink) {
gabeLink.style.color = fgColor;
}
// Clear previous error
errorMessage.textContent = '';
downloadBtn.style.display = 'none';
// Validate input
if (text === '') {
errorMessage.textContent = 'Please enter text or URL';
// Hide both canvas and image
qrcodeCanvas.style.display = 'none';
qrcodeImg.style.display = 'none';
return;
}
// Create new QR code on canvas
try {
if (!qr) {
qr = new QRious({
element: qrcodeCanvas,
size: size,
value: text,
foreground: fgColor,
background: bgColor,
level: errorCorrection
});
} else {
qr.set({
size: size,
value: text,
foreground: fgColor,
background: bgColor,
level: errorCorrection
});
}
// Convert canvas to image
const dataURL = qrcodeCanvas.toDataURL('image/png');
qrcodeImg.src = dataURL;
// Show image (hide canvas) and download button
qrcodeCanvas.style.display = 'none';
qrcodeImg.style.display = 'block';
downloadBtn.style.display = 'inline-block';
} catch (err) {
errorMessage.textContent = 'Error generating QR code: ' + err.message;
qrcodeCanvas.style.display = 'none';
qrcodeImg.style.display = 'none';
}
}
function downloadQRCode() {
// Use the image source for download
const link = document.createElement('a');
link.download = 'qrcode.png';
link.href = qrcodeImg.src;
// Simulate click to trigger download
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
// Show success feedback
const originalText = downloadBtn.textContent;
downloadBtn.textContent = 'Downloaded!';
// Reset button after a short delay
setTimeout(() => {
downloadBtn.textContent = originalText;
}, 2000);
}
});
</script>
</body></html>