dev.to

How to make a QR Code generator using JavaScript?

Murtuzaali Surti
Murtuzaali Surti

• 5 min read

Updated On

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. So, 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:

See the pen (@seekertruth) on CodePen.

Here's the github repository for this project.

That's all for now. I am on Twitter as well as GitHub.

This post was originally published in dev.to.


Skeleton Loading for Social Media Embeds using CSS and JavaScript 🔥

Previous

IIFE in JavaScript

Next