QR-Generator-Pro / index.html
DotSlashGabut's picture
Update index.html
dc21927 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>QR Code Generator Pro</title>
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 10px;
}
.container {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
padding: 30px;
max-width: 500px;
width: 100%;
animation: slideUp 0.8s ease-out;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.header {
text-align: center;
margin-bottom: 25px;
}
.title {
font-size: 28px;
font-weight: 700;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 8px;
}
.subtitle {
color: #666;
font-size: 14px;
}
.category-selector {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
gap: 8px;
margin-bottom: 20px;
}
.category-btn {
padding: 10px 8px;
border: none;
border-radius: 12px;
background: #f8f9ff;
color: #666;
font-size: 12px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
.category-btn:hover {
background: #e8f0ff;
transform: translateY(-2px);
}
.category-btn.active {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.category-icon {
font-size: 16px;
}
.input-group {
margin-bottom: 15px;
}
.input-label {
display: block;
margin-bottom: 6px;
font-weight: 600;
color: #333;
font-size: 13px;
}
.input-field {
width: 100%;
padding: 12px 16px;
border: 2px solid #e9ecef;
border-radius: 12px;
font-size: 14px;
transition: all 0.3s ease;
background: #fafbff;
}
.input-field:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
background: white;
}
.input-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.customization {
background: #f8f9ff;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
}
.custom-title {
font-weight: 600;
color: #333;
margin-bottom: 15px;
font-size: 14px;
}
.color-controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 15px;
margin-bottom: 15px;
}
.color-group {
display: flex;
align-items: center;
gap: 10px;
}
.color-input {
width: 40px;
height: 40px;
border: none;
border-radius: 8px;
cursor: pointer;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.size-control {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 10px;
}
.size-slider {
flex: 1;
height: 6px;
background: #e9ecef;
border-radius: 3px;
outline: none;
cursor: pointer;
}
.generate-btn {
width: 100%;
padding: 15px;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
margin-bottom: 20px;
}
.generate-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3);
}
.generate-btn:active {
transform: translateY(0);
}
.qr-output {
text-align: center;
padding: 20px;
background: white;
border-radius: 12px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
}
.qr-canvas {
max-width: 100%;
border-radius: 8px;
margin-bottom: 15px;
}
.download-controls {
display: flex;
gap: 10px;
justify-content: center;
flex-wrap: wrap;
}
.download-btn {
padding: 10px 20px;
border: 2px solid #667eea;
background: white;
color: #667eea;
border-radius: 8px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
}
.download-btn:hover {
background: #667eea;
color: white;
}
.hidden {
display: none;
}
.error {
color: #e74c3c;
font-size: 12px;
margin-top: 5px;
}
@media (max-width: 480px) {
.container {
padding: 20px;
margin: 10px;
}
.category-selector {
grid-template-columns: repeat(3, 1fr);
}
.input-row {
grid-template-columns: 1fr;
}
.color-controls {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1 class="title">QR Generator Pro</h1>
<p class="subtitle">Create professional QR codes with advanced customization</p>
</div>
<div class="category-selector">
<button class="category-btn active" data-type="text">
<span class="category-icon">📝</span>
<span>Text</span>
</button>
<button class="category-btn" data-type="url">
<span class="category-icon">🔗</span>
<span>URL</span>
</button>
<button class="category-btn" data-type="email">
<span class="category-icon">✉️</span>
<span>Email</span>
</button>
<button class="category-btn" data-type="phone">
<span class="category-icon">📞</span>
<span>Phone</span>
</button>
<button class="category-btn" data-type="sms">
<span class="category-icon">💬</span>
<span>SMS</span>
</button>
<button class="category-btn" data-type="wifi">
<span class="category-icon">📶</span>
<span>WiFi</span>
</button>
<button class="category-btn" data-type="vcard">
<span class="category-icon">👤</span>
<span>vCard</span>
</button>
<button class="category-btn" data-type="location">
<span class="category-icon">📍</span>
<span>Location</span>
</button>
<button class="category-btn" data-type="event">
<span class="category-icon">📅</span>
<span>Event</span>
</button>
</div>
<div id="input-forms">
<!-- Text Form -->
<div id="text-form" class="form-section">
<div class="input-group">
<label class="input-label">Enter your text</label>
<textarea class="input-field" id="text-input" rows="3" placeholder="Type your message here..."></textarea>
</div>
</div>
<!-- URL Form -->
<div id="url-form" class="form-section hidden">
<div class="input-group">
<label class="input-label">Website URL</label>
<input type="url" class="input-field" id="url-input" placeholder="https://example.com">
</div>
</div>
<!-- Email Form -->
<div id="email-form" class="form-section hidden">
<div class="input-group">
<label class="input-label">Email Address</label>
<input type="email" class="input-field" id="email-input" placeholder="user@example.com">
</div>
<div class="input-group">
<label class="input-label">Subject (Optional)</label>
<input type="text" class="input-field" id="email-subject" placeholder="Email subject">
</div>
<div class="input-group">
<label class="input-label">Message (Optional)</label>
<textarea class="input-field" id="email-body" rows="2" placeholder="Email message"></textarea>
</div>
</div>
<!-- Phone Form -->
<div id="phone-form" class="form-section hidden">
<div class="input-group">
<label class="input-label">Phone Number</label>
<input type="tel" class="input-field" id="phone-input" placeholder="+1234567890">
</div>
</div>
<!-- SMS Form -->
<div id="sms-form" class="form-section hidden">
<div class="input-group">
<label class="input-label">Phone Number</label>
<input type="tel" class="input-field" id="sms-phone" placeholder="+1234567890">
</div>
<div class="input-group">
<label class="input-label">Message</label>
<textarea class="input-field" id="sms-message" rows="2" placeholder="SMS message"></textarea>
</div>
</div>
<!-- WiFi Form -->
<div id="wifi-form" class="form-section hidden">
<div class="input-group">
<label class="input-label">Network Name (SSID)</label>
<input type="text" class="input-field" id="wifi-ssid" placeholder="My WiFi Network">
</div>
<div class="input-row">
<div class="input-group">
<label class="input-label">Password</label>
<input type="text" class="input-field" id="wifi-password" placeholder="password123">
</div>
<div class="input-group">
<label class="input-label">Security</label>
<select class="input-field" id="wifi-security">
<option value="WPA">WPA/WPA2</option>
<option value="WEP">WEP</option>
<option value="nopass">None</option>
</select>
</div>
</div>
</div>
<!-- vCard Form -->
<div id="vcard-form" class="form-section hidden">
<div class="input-row">
<div class="input-group">
<label class="input-label">First Name</label>
<input type="text" class="input-field" id="vcard-firstname" placeholder="John">
</div>
<div class="input-group">
<label class="input-label">Last Name</label>
<input type="text" class="input-field" id="vcard-lastname" placeholder="Doe">
</div>
</div>
<div class="input-group">
<label class="input-label">Organization</label>
<input type="text" class="input-field" id="vcard-org" placeholder="Company Name">
</div>
<div class="input-row">
<div class="input-group">
<label class="input-label">Phone</label>
<input type="tel" class="input-field" id="vcard-phone" placeholder="+1234567890">
</div>
<div class="input-group">
<label class="input-label">Email</label>
<input type="email" class="input-field" id="vcard-email" placeholder="john@example.com">
</div>
</div>
</div>
<!-- Location Form -->
<div id="location-form" class="form-section hidden">
<div class="input-row">
<div class="input-group">
<label class="input-label">Latitude</label>
<input type="number" class="input-field" id="location-lat" placeholder="40.7128" step="any">
</div>
<div class="input-group">
<label class="input-label">Longitude</label>
<input type="number" class="input-field" id="location-lng" placeholder="-74.0060" step="any">
</div>
</div>
</div>
<!-- Event Form -->
<div id="event-form" class="form-section hidden">
<div class="input-group">
<label class="input-label">Event Title</label>
<input type="text" class="input-field" id="event-title" placeholder="Meeting with Team">
</div>
<div class="input-row">
<div class="input-group">
<label class="input-label">Start Date</label>
<input type="datetime-local" class="input-field" id="event-start">
</div>
<div class="input-group">
<label class="input-label">End Date</label>
<input type="datetime-local" class="input-field" id="event-end">
</div>
</div>
<div class="input-group">
<label class="input-label">Location (Optional)</label>
<input type="text" class="input-field" id="event-location" placeholder="Conference Room A">
</div>
</div>
</div>
<div class="customization">
<div class="custom-title">🎨 Customization</div>
<div class="color-controls">
<div class="color-group">
<input type="color" class="color-input" id="fg-color" value="#000000">
<span>Foreground</span>
</div>
<div class="color-group">
<input type="color" class="color-input" id="bg-color" value="#ffffff">
<span>Background</span>
</div>
</div>
<div class="size-control">
<span>Size:</span>
<input type="range" class="size-slider" id="size-slider" min="128" max="400" value="256">
<span id="size-display">256px</span>
</div>
</div>
<button class="generate-btn" onclick="generateQR()">
Generate QR Code
</button>
<div id="qr-output" class="qr-output hidden">
<canvas id="qr-canvas" class="qr-canvas"></canvas>
<div class="download-controls">
<button class="download-btn" onclick="downloadQR('png')">PNG</button>
<button class="download-btn" onclick="downloadQR('jpg')">JPG</button>
<button class="download-btn" onclick="downloadQR('svg')">SVG</button>
</div>
</div>
</div>
<script>
let currentType = 'text';
let currentQRData = '';
// Category switching
document.querySelectorAll('.category-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const type = btn.dataset.type;
currentType = type;
document.querySelectorAll('.form-section').forEach(form => form.classList.add('hidden'));
document.getElementById(`${type}-form`).classList.remove('hidden');
});
});
// Size slider
document.getElementById('size-slider').addEventListener('input', (e) => {
document.getElementById('size-display').textContent = e.target.value + 'px';
});
function generateQRData() {
switch (currentType) {
case 'text':
return document.getElementById('text-input').value;
case 'url':
const url = document.getElementById('url-input').value;
return url.startsWith('http') ? url : `https://${url}`;
case 'email':
const email = document.getElementById('email-input').value;
const subject = document.getElementById('email-subject').value;
const body = document.getElementById('email-body').value;
let mailto = `mailto:${email}`;
const params = [];
if (subject) params.push(`subject=${encodeURIComponent(subject)}`);
if (body) params.push(`body=${encodeURIComponent(body)}`);
if (params.length) mailto += '?' + params.join('&');
return mailto;
case 'phone':
return `tel:${document.getElementById('phone-input').value}`;
case 'sms':
const smsPhone = document.getElementById('sms-phone').value;
const smsMessage = document.getElementById('sms-message').value;
return `sms:${smsPhone}${smsMessage ? `?body=${encodeURIComponent(smsMessage)}` : ''}`;
case 'wifi':
const ssid = document.getElementById('wifi-ssid').value;
const password = document.getElementById('wifi-password').value;
const security = document.getElementById('wifi-security').value;
return `WIFI:T:${security};S:${ssid};P:${password};;`;
case 'vcard':
const firstName = document.getElementById('vcard-firstname').value;
const lastName = document.getElementById('vcard-lastname').value;
const org = document.getElementById('vcard-org').value;
const phone = document.getElementById('vcard-phone').value;
const vcardEmail = document.getElementById('vcard-email').value;
return `BEGIN:VCARD
VERSION:3.0
FN:${firstName} ${lastName}
N:${lastName};${firstName};;;
ORG:${org}
TEL:${phone}
EMAIL:${vcardEmail}
END:VCARD`;
case 'location':
const lat = document.getElementById('location-lat').value;
const lng = document.getElementById('location-lng').value;
return `geo:${lat},${lng}`;
case 'event':
const title = document.getElementById('event-title').value;
const start = document.getElementById('event-start').value;
const end = document.getElementById('event-end').value;
const location = document.getElementById('event-location').value;
const formatDate = (dateStr) => {
return new Date(dateStr).toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z';
};
return `BEGIN:VEVENT
SUMMARY:${title}
DTSTART:${formatDate(start)}
DTEND:${formatDate(end)}
LOCATION:${location}
END:VEVENT`;
default:
return '';
}
}
function generateQR() {
const data = generateQRData();
if (!data.trim()) {
alert('Please enter some data to generate QR code');
return;
}
currentQRData = data;
const canvas = document.getElementById('qr-canvas');
const fgColor = document.getElementById('fg-color').value;
const bgColor = document.getElementById('bg-color').value;
const size = parseInt(document.getElementById('size-slider').value);
QRCode.toCanvas(canvas, data, {
width: size,
height: size,
color: {
dark: fgColor,
light: bgColor
},
errorCorrectionLevel: 'M',
margin: 2
}, (error) => {
if (error) {
console.error(error);
alert('Error generating QR code');
} else {
document.getElementById('qr-output').classList.remove('hidden');
canvas.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
});
}
function downloadQR(format) {
const canvas = document.getElementById('qr-canvas');
if (format === 'svg') {
// Generate SVG version
QRCode.toString(currentQRData, {
type: 'svg',
width: parseInt(document.getElementById('size-slider').value),
color: {
dark: document.getElementById('fg-color').value,
light: document.getElementById('bg-color').value
}
}, (err, string) => {
if (!err) {
const blob = new Blob([string], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `qrcode.svg`;
a.click();
URL.revokeObjectURL(url);
}
});
} else {
// PNG or JPG
const mimeType = format === 'png' ? 'image/png' : 'image/jpeg';
const url = canvas.toDataURL(mimeType, 0.9);
const a = document.createElement('a');
a.href = url;
a.download = `qrcode.${format}`;
a.click();
}
}
// Auto-generate on input for better UX
document.addEventListener('input', (e) => {
if (e.target.classList.contains('input-field') || e.target.id === 'size-slider') {
// Debounce auto-generation
clearTimeout(window.autoGenTimeout);
window.autoGenTimeout = setTimeout(() => {
const data = generateQRData();
if (data.trim()) {
generateQR();
}
}, 500);
}
});
// Initialize with sample data
document.getElementById('text-input').value = 'Hello, World! 👋';
generateQR();
</script>
</body>
</html>