This post was originally published on dev.to/murtuzaalisurti.
While you can generate QR codes for URLs in browsers such as Chrome it's always interesting to learn how you can make your own version of a simple QR code generator. Here we go.
HTML
Here's a quick look at the HTML code and it's pretty straightforward.
<section class="heading">
<div class="title">QRcodes</div>
<div class="sub-title">Generate QRCode for anything!</div>
</section>
<section class="user-input">
<label for="input_text">Type something...</label>
<input type="text" name="input_text" id="input_text" autocomplete="off">
<button class="button" type="submit">Generate QR Code</button>
</section>
<div class="qr-code" style="display: none;"></div>
<script src="./js/app.js"></script>
The last element is for the QR code to be displayed as soon as we fetch it from a library through javascript (more on that later).
Let's move on to some javascript.
JavaScript
First of all, we will create an event for when the user clicks on the Generate QR code
button.
let btn = document.querySelector(".button");
btn.addEventListener("click", () => {
//code
})
Now, we are going to create a function known as generate()
which will be invoked as soon as the user clicks on the Generate QR code
button. This function will take the text input from the user as a parameter.
function generate(user_input) {
//code
}
Inside this function, we are going to use a javascript library qrcode.js to generate QR code. You can use this library via a CDN by including the below <script>
tag in the <head>
tag of html
.
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
Inside the generate()
function, we will create a new object using the given library. It will take two arguments, first is the element in which the QR code has to be displayed and secondly, the content for which the QR code has to be generated and some options to customize the QR code.
function generate(user_input) {
var qrcode = new QRCode(document.querySelector(".qr-code"), {
text: `${user_input.value}`,
width: 180, //default 128
height: 180,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.H
});
}
Next, we will create a download button and append it below the QR code.
let download = document.createElement("button");
document.querySelector(".qr-code").appendChild(download);
Inside this download button we will add a link which allows users to download the QR code with a specified file name and append it into the download button. You can learn more about the download attribute here.
let download_link = document.createElement("a");
download_link.setAttribute("download", "qr_code_linq.png");
download_link.innerText = "Download";
download.appendChild(download_link);
Let's figure out the href
attribute of the <a>
tag next.
The qrcode
object will return a canvas
element as well as an image
element.
For smartphones, the canvas
element will be visible but for desktop, the image
element will be visible having a src
attribute set to a dataURL
. We will use the dataURL
to download the QR code.
In the case of desktop, it's pretty obvious. We just have to grab the value of src
attribute of the image element and assign it to the href
attribute of the download link (<a>
tag) after a specified amount of time (0.3 seconds) using setTimeout()
function because the QR code takes some time to be generated.
let qr_code_img = document.querySelector(".qr-code img");
setTimeout(() => {
download_link.setAttribute("href", `${qr_code_img.getAttribute("src")}`);
}, 300);
But how do we get the dataURL
from the canvas element? By using the method toDataURL()
on the canvas
element.
let qr_code_canvas = document.querySelector("canvas");
setTimeout(() => {
download_link.setAttribute("href", `${qr_code_canvas.toDataURL()}`);
}, 300);
After applying some logic, we get this:
if(qr_code_img.getAttribute("src") == null){
setTimeout(() => {
download_link.setAttribute("href", `${qr_code_canvas.toDataURL()}`);
}, 300);
} else {
setTimeout(() => {
download_link.setAttribute("href", `${qr_code_img.getAttribute("src")}`);
}, 300);
}
Also, the .qr-code
element will be hidden until the user clicks on the Generate QR code
button. With this, our generate()
function is all set to be invoked.
function generate(user_input){
document.querySelector(".qr-code").style = "";
var qrcode = new QRCode(document.querySelector(".qr-code"), {
text: `${user_input.value}`,
width: 180, //128
height: 180,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.H
});
console.log(qrcode);
let download = document.createElement("button");
document.querySelector(".qr-code").appendChild(download);
let download_link = document.createElement("a");
download_link.setAttribute("download", "qr_code_linq.png");
download_link.innerText = "Download";
download.appendChild(download_link);
if(document.querySelector(".qr-code img").getAttribute("src") == null){
setTimeout(() => {
download_link.setAttribute("href", `${document.querySelector("canvas").toDataURL()}`);
}, 300);
} else {
setTimeout(() => {
download_link.setAttribute("href", `${document.querySelector(".qr-code img").getAttribute("src")}`);
}, 300);
}
}
Now inside our click event function, we will check if there is already a QR code displayed or not. If it is, then we will first clear that QR code and generate a new one. If it's not present, we can simply generate a new one.
Also, all of this happens only if the user enters some text or if the input value is not empty.
btn.addEventListener("click", () => {
let user_input = document.querySelector("#input_text");
if(user_input.value != "") {
if(document.querySelector(".qr-code").childElementCount == 0){
generate(user_input);
} else{
document.querySelector(".qr-code").innerHTML = "";
generate(user_input);
}
} else {
document.querySelector(".qr-code").style = "display: none";
console.log("not valid input");
}
})
You can style the elements the way as you want. Here are the styles that I went for:
:root{
font-size: 62.5%;
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
text-size-adjust: none;
-webkit-text-size-adjust: none;
}
button:hover{
cursor: pointer;
}
body{
display: flex;
flex-direction: column;
align-items: center;
background-color: #EAE6E5;
}
.heading{
margin: 3rem 0 5rem 0;
}
.title, .sub-title{
font-size: 4rem;
text-align: center;
font-family: 'Poppins', sans-serif;
color: #12130F;
}
.sub-title{
font-size: 1.5rem;
color: #8F8073;
}
.user-input{
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.user-input label{
text-align: center;
font-size: 1.5rem;
font-family: 'Poppins', sans-serif;
}
.user-input input{
width: 80%;
max-width: 35rem;
font-family: 'Poppins', sans-serif;
outline: none;
border: none;
border-radius: 0.5rem;
background-color: #9b8774ad;
text-align: center;
padding: 0.7rem 1rem;
margin: 1rem 1rem 2rem 1rem;
}
.button{
outline: none;
border: none;
border-radius: 0.5rem;
padding: 0.7rem 1rem;
margin-bottom: 3rem;
background-color: #5b92799d;
color: #12130F;
font-family: 'Poppins', sans-serif;
}
.qr-code{
border-top: 0.5rem solid #8F8073;
border-right: 0.5rem solid #8F8073;
border-bottom: 1rem solid #8F8073;
border-radius: 0.5rem;
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
border-left: 0.5rem solid #8F8073;
background-color: #8F8073;
}
.qr-code button{
display: flex;
justify-content: center;
background-color: #8F8073;
font-family: 'Poppins', sans-serif;
color: #EAE6E5;
border: none;
outline: none;
width: 100%;
height: 100%;
margin-top: 1rem;
}
.qr-code button a{
width: 100%;
height: 100%;
text-decoration: none;
color: #EAE6E5;
}
Here is a demo of the entire project:
Here's the github repository for this project.