Skip to content

Commit ccb57fb

Browse files
Merge pull request #153 from AtharvaPatil86/main
Added Qr Code generator and download qr feature
2 parents f68a1c7 + b99e18a commit ccb57fb

3 files changed

Lines changed: 268 additions & 20 deletions

File tree

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,46 @@
11
<!DOCTYPE html>
22
<html lang="en">
33
<head>
4-
<meta charset="UTF-8">
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
66
<title>QR Code Generator & Scanner</title>
7-
<link rel="stylesheet" href="styles.css">
7+
8+
<!-- Styles -->
9+
<link rel="stylesheet" href="styles.css" />
10+
11+
<!-- Libraries -->
12+
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
13+
<script src="https://unpkg.com/html5-qrcode"></script>
814
</head>
15+
916
<body>
1017
<h1>QR Code Generator & Scanner</h1>
18+
1119
<div id="qr-container">
12-
<!-- TODO: Input for text/URL to generate QR code -->
13-
<!-- TODO: Display generated QR code -->
14-
<!-- TODO: Option to download QR code -->
15-
<!-- TODO: Input for uploading/scanning QR code image -->
16-
<!-- TODO: Display scanned QR code result -->
20+
<!-- QR Generator Section -->
21+
<section class="generator">
22+
<h2>Generate a QR Code</h2>
23+
<input
24+
id="qr-input"
25+
type="text"
26+
placeholder="Enter text or URL..."
27+
aria-label="QR code input"
28+
/>
29+
<button id="generate-btn">Generate</button>
30+
31+
<div id="qrcode"></div>
32+
33+
<button id="download-btn" class="hidden">Download QR</button>
34+
</section>
35+
36+
<!-- QR Scanner Section -->
37+
<section class="scanner">
38+
<h2>Scan a QR Code</h2>
39+
<div id="reader" style="width: 300px; margin: auto;"></div>
40+
<p id="scan-result"></p>
41+
</section>
1742
</div>
43+
1844
<script src="main.js"></script>
1945
</body>
20-
</html>
46+
</html>
Lines changed: 116 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,120 @@
1-
// TODO: Generate QR code from input text/URL
2-
// TODO: Display generated QR code
3-
// TODO: Download QR code image
4-
// TODO: Scan uploaded QR code image
5-
// TODO: Display scanned QR code result
61

72
function initQRCodeGeneratorScanner() {
8-
// TODO: Generate QR code from input
9-
// TODO: Scan QR code from image
10-
// TODO: Display results
11-
// TODO: Download QR code
3+
const qrContainer = document.getElementById("qr-container");
4+
5+
6+
qrContainer.innerHTML = `
7+
<section class="generator">
8+
<h2>Generate a QR Code</h2>
9+
<input id="qr-input" type="text" placeholder="Enter text or URL..." />
10+
<button id="generate-btn">Generate</button>
11+
<div id="qrcode"></div>
12+
<button id="download-btn" class="hidden">Download QR</button>
13+
</section>
14+
15+
<section class="scanner">
16+
<h2>Scan a QR Code (Upload Image)</h2>
17+
<input id="file-input" type="file" accept="image/*" />
18+
<p id="scan-result"></p>
19+
</section>
20+
`;
21+
22+
const qrInput = document.getElementById("qr-input");
23+
const generateBtn = document.getElementById("generate-btn");
24+
const qrContainerEl = document.getElementById("qrcode");
25+
const downloadBtn = document.getElementById("download-btn");
26+
const fileInput = document.getElementById("file-input");
27+
const resultEl = document.getElementById("scan-result");
28+
29+
let qrCodeInstance = null;
30+
31+
generateBtn.addEventListener("click", () => {
32+
const text = qrInput.value.trim();
33+
if (!text) {
34+
alert("Please enter some text or a URL!");
35+
return;
36+
}
37+
38+
qrContainerEl.innerHTML = "";
39+
40+
qrCodeInstance = new QRCode(qrContainerEl, {
41+
text,
42+
width: 200,
43+
height: 200,
44+
});
45+
46+
downloadBtn.classList.remove("hidden");
47+
});
48+
49+
downloadBtn.addEventListener("click", () => {
50+
const img = qrContainerEl.querySelector("img");
51+
if (!img) {
52+
alert("Please generate a QR code first!");
53+
return;
54+
}
55+
56+
const link = document.createElement("a");
57+
link.href = img.src;
58+
link.download = "qrcode.png";
59+
link.click();
60+
});
61+
62+
63+
fileInput.addEventListener("change", async (e) => {
64+
const file = e.target.files[0];
65+
if (!file) return;
66+
67+
const reader = new FileReader();
68+
reader.onload = async function () {
69+
const imageDataUrl = reader.result;
70+
resultEl.textContent = "Scanning...";
71+
72+
try {
73+
const result = await scanQRCodeFromImage(imageDataUrl);
74+
if (result) {
75+
resultEl.textContent = `Scanned Result: ${result}`;
76+
} else {
77+
resultEl.textContent = "No QR code detected.";
78+
}
79+
} catch (err) {
80+
console.error(err);
81+
resultEl.textContent = "Error scanning QR code.";
82+
}
83+
};
84+
reader.readAsDataURL(file);
85+
});
86+
}
87+
88+
async function scanQRCodeFromImage(imageDataUrl) {
89+
return new Promise((resolve, reject) => {
90+
const img = new Image();
91+
img.onload = () => {
92+
const canvas = document.createElement("canvas");
93+
const ctx = canvas.getContext("2d");
94+
canvas.width = img.width;
95+
canvas.height = img.height;
96+
ctx.drawImage(img, 0, 0, img.width, img.height);
97+
98+
const imageData = ctx.getImageData(0, 0, img.width, img.height);
99+
100+
101+
if (typeof jsQR === "undefined") {
102+
const script = document.createElement("script");
103+
script.src = "https://cdn.jsdelivr.net/npm/jsqr/dist/jsQR.js";
104+
script.onload = () => {
105+
const code = jsQR(imageData.data, imageData.width, imageData.height);
106+
resolve(code ? code.data : null);
107+
};
108+
script.onerror = () => reject("Failed to load jsQR library.");
109+
document.body.appendChild(script);
110+
} else {
111+
const code = jsQR(imageData.data, imageData.width, imageData.height);
112+
resolve(code ? code.data : null);
113+
}
114+
};
115+
img.onerror = reject;
116+
img.src = imageDataUrl;
117+
});
12118
}
13119

14-
window.addEventListener('DOMContentLoaded', initQRCodeGeneratorScanner);
120+
window.addEventListener("DOMContentLoaded", initQRCodeGeneratorScanner);
Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,117 @@
1-
/* TODO: Style QR container, input, QR code display, download button, scan input, result display */
1+
2+
3+
body {
4+
font-family: system-ui, sans-serif;
5+
text-align: center;
6+
padding: 2rem 1rem;
7+
background-color: var(--bg, #fafafa);
8+
color: var(--text, #222);
9+
}
10+
11+
h1 {
12+
font-size: 1.8rem;
13+
margin-bottom: 1.5rem;
14+
}
15+
16+
section {
17+
margin: 2rem auto;
18+
max-width: 400px;
19+
background-color: #fff;
20+
border: 1px solid #ddd;
21+
border-radius: 8px;
22+
padding: 1.5rem;
23+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
24+
}
25+
26+
h2 {
27+
font-size: 1.2rem;
28+
margin-bottom: 1rem;
29+
}
30+
31+
input[type="text"],
32+
input[type="file"] {
33+
width: 100%;
34+
padding: 0.6rem;
35+
font-size: 1rem;
36+
border: 1px solid #ccc;
37+
border-radius: 4px;
38+
margin-bottom: 0.75rem;
39+
box-sizing: border-box;
40+
}
41+
42+
button {
43+
background-color: #007bff;
44+
color: white;
45+
border: none;
46+
border-radius: 4px;
47+
padding: 0.6rem 1.2rem;
48+
font-size: 1rem;
49+
cursor: pointer;
50+
transition: background-color 0.2s ease;
51+
}
52+
53+
button:hover {
54+
background-color: #005fcc;
55+
}
56+
57+
button.hidden {
58+
display: none;
59+
}
60+
61+
#qrcode {
62+
margin: 1rem auto;
63+
}
64+
65+
#scan-result {
66+
margin-top: 0.75rem;
67+
font-weight: 500;
68+
color: #333;
69+
word-break: break-word;
70+
}
71+
72+
#file-input {
73+
margin-top: 0.5rem;
74+
}
75+
76+
#qr-container {
77+
display: flex;
78+
flex-direction: column;
79+
align-items: center;
80+
gap: 2rem;
81+
}
82+
83+
body.dark-mode {
84+
background-color: #121212;
85+
color: #e0e0e0;
86+
}
87+
88+
body.dark-mode section {
89+
background-color: #1e1e1e;
90+
border-color: #333;
91+
}
92+
93+
body.dark-mode input,
94+
body.dark-mode button {
95+
background-color: #2a2a2a;
96+
color: #eee;
97+
border-color: #444;
98+
}
99+
100+
body.dark-mode button {
101+
background-color: #4e8cff;
102+
}
103+
104+
body.dark-mode button:hover {
105+
background-color: #3c6fd1;
106+
}
107+
108+
@media (max-width: 600px) {
109+
body {
110+
padding: 1rem;
111+
}
112+
113+
section {
114+
width: 100%;
115+
padding: 1rem;
116+
}
117+
}

0 commit comments

Comments
 (0)