How to make a QR Code generator using JavaScript?
Tags: webdev, javascript, tutorial, beginners
Published: 2021-12-23 07:52:46

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.

```html

<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.

```javascript

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.

```javascript

function generate(user_input) {
    //code
} 

```

Inside this function, we are going to use a javascript library [qrcode.js](https://davidshimjs.github.io/qrcodejs/) to generate QR code. You can use this library via a CDN by including the below `<script>` tag in the `<head>` tag of `html`.

```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.

```javascript

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.

```javascript

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](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download).

```javascript

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. 

```javascript

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.

```javascript

let qr_code_canvas = document.querySelector("canvas");
setTimeout(() => {
    download_link.setAttribute("href", `${qr_code_canvas.toDataURL()}`);
}, 300);

```

After applying some logic, we get this:

```javascript

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.

```javascript

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.

```javascript

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:

```css

: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:

{% codepen https://codepen.io/seekertruth/pen/XWeeVrG %}

Here's the [github repository](https://github.com/murtuzaalisurti/qr) for this project.

{% github murtuzaalisurti/qr no-readme %}

That's all for now. I am on [Twitter](https://twitter.com/murtuza_surti) as well as [GitHub](https://github.com/murtuzaalisurti).