Building a 6-Digit Passcode Input in Plain JavaScript

Building a 6-Digit Passcode Input in Plain JavaScript

In this tutorial, we’ll create a seamless passcode input system for a 6-digit activation code. This setup ensures user-friendliness, supports direct typing or pasting of the code, and triggers a verification function when all digits are entered.


Part 1: HTML Structure

Start with a form that includes:

  • A placeholder for the passcode input fields.
  • A link for resending the code.

Here’s the updated HTML:

<form class="app-signup-wrapper">
    <div class="app-plan-wrapper"></div>
    <label class="form-label app-activation-label">
        <p>We have sent a 6-number code to</p>
        <p><strong>user@example.com</strong></p>
        <p>The code expires in 1 hour, so please hurry.</p>
    </label>
    <div class="app-code-activation-wrapper"></div>
    <a href="#" class="app-code-activation-resend" data-sent="false">Did not receive it? Re-Send Now</a>
</form>

Part 2: JavaScript for Passcode Inputs

We’ll create six input fields dynamically, handle user interactions, and trigger the verification logic upon completion.

Step 1: Dynamically Add Input Fields

const codeActivationWrapper = document.querySelector('.app-code-activation-wrapper');
const numOfFields = 6;

// Create and append six input fields
for (let i = 0; i < numOfFields; i++) {
    const input = document.createElement('input');
    input.type = 'text';
    input.className = 'form-control app-activation-code-input';
    input.maxLength = 1;
    codeActivationWrapper.appendChild(input);
}

This script adds six input fields to the .app-code-activation-wrapper div, each restricted to one character using maxLength.


Step 2: Handling Paste Events

Allow users to paste the full code. If the pasted text is valid, split it across the input fields.

const fields = document.querySelectorAll('.app-activation-code-input');

fields.forEach((field, index) => {
    field.addEventListener('paste', (event) => {
        event.preventDefault();
        const pasteData = (event.clipboardData || window.clipboardData).getData('text').trim();

        if (/^\d{6}$/.test(pasteData)) {
            // Distribute pasted digits into input fields
            [...pasteData].forEach((char, idx) => {
                if (fields[idx]) fields[idx].value = char;
            });
            fields[5].focus(); // Focus the last field
            verifyActivationCode(); // Call verification
        }
    });
});

2228+ FREE RESOURCES FOR DEVELOPERS!! ❤️😍🥳 (updated daily)
1400+ Free HTML Templates
359+ Free News Articles
69+ Free AI Prompts
323+ Free Code Libraries
52+ Free Code Snippets & Boilerplates for Node, Nuxt, Vue, and more!
25+ Free Open Source Icon Libraries
Visit dailysandbox.pro for free access to a treasure trove of resources!

Step 3: Handling Input and Navigation

Automatically move to the next field on input and handle backspace for navigation.

fields.forEach((field, index) => {
    field.addEventListener('input', () => {
        if (field.value && index < fields.length - 1) {
            fields[index + 1].focus();
        }
        checkCompletion(); // Check if all fields are filled
    });

    field.addEventListener('keydown', (event) => {
        if (event.key === 'Backspace' && !field.value && index > 0) {
            fields[index - 1].focus();
        }
    });
});

Step 4: Check for Completion

When all six fields are filled, concatenate their values and trigger the verifyActivationCode function.

const checkCompletion = () => {
    const activationCode = Array.from(fields).map((field) => field.value).join('');
    if (activationCode.length === 6) {
        verifyActivationCode(activationCode);
    }
};

Step 5: Verification Logic

Simulate the verification process with a function that sends the code to a backend server.

const verifyActivationCode = (activationCode) => {
    console.log('Verifying code:', activationCode);

    const spinner = document.createElement('div');
    spinner.className = 'spinner';
    document.body.appendChild(spinner);

    // Simulate an AJAX request
    setTimeout(() => {
        spinner.remove();
        if (activationCode === '123456') {
            alert('Code verified successfully!');
        } else {
            alert('Invalid code. Try again.');
            fields.forEach((field) => (field.value = ''));
            fields[0].focus();
        }
    }, 2000);
};

Add functionality to resend the activation code.

const resendLink = document.querySelector('.app-code-activation-resend');

resendLink.addEventListener('click', (event) => {
    event.preventDefault();

    // Simulate a resend action
    resendLink.setAttribute('data-sent', 'true');
    setTimeout(() => {
        resendLink.setAttribute('data-sent', 'false');
        alert('Activation code resent!');
    }, 5000);
});

Complete JavaScript Code

Here’s the complete script:

const codeActivationWrapper = document.querySelector('.app-code-activation-wrapper');
const resendLink = document.querySelector('.app-code-activation-resend');
const numOfFields = 6;

// Create input fields dynamically
for (let i = 0; i < numOfFields; i++) {
    const input = document.createElement('input');
    input.type = 'text';
    input.className = 'form-control app-activation-code-input';
    input.maxLength = 1;
    codeActivationWrapper.appendChild(input);
}

const fields = document.querySelectorAll('.app-activation-code-input');

// Handle paste events
fields.forEach((field, index) => {
    field.addEventListener('paste', (event) => {
        event.preventDefault();
        const pasteData = (event.clipboardData || window.clipboardData).getData('text').trim();

        if (/^\d{6}$/.test(pasteData)) {
            [...pasteData].forEach((char, idx) => {
                if (fields[idx]) fields[idx].value = char;
            });
            fields[5].focus();
            verifyActivationCode(Array.from(fields).map((field) => field.value).join(''));
        }
    });
});

// Handle input and navigation
fields.forEach((field, index) => {
    field.addEventListener('input', () => {
        if (field.value && index < fields.length - 1) {
            fields[index + 1].focus();
        }
        checkCompletion();
    });

    field.addEventListener('keydown', (event) => {
        if (event.key === 'Backspace' && !field.value && index > 0) {
            fields[index - 1].focus();
        }
    });
});

// Check for completion
const checkCompletion = () => {
    const activationCode = Array.from(fields).map((field) => field.value).join('');
    if (activationCode.length === 6) {
        verifyActivationCode(activationCode);
    }
};

// Simulate code verification
const verifyActivationCode = (activationCode) => {
    console.log('Verifying code:', activationCode);

    const spinner = document.createElement('div');
    spinner.className = 'spinner';
    document.body.appendChild(spinner);

    setTimeout(() => {
        spinner.remove();
        if (activationCode === '123456') {
            alert('Code verified successfully!');
        } else {
            alert('Invalid code. Try again.');
            fields.forEach((field) => (field.value = ''));
            fields[0].focus();
        }
    }, 2000);
};

// Handle resend link
resendLink.addEventListener('click', (event) => {
    event.preventDefault();

    resendLink.setAttribute('data-sent', 'true');
    setTimeout(() => {
        resendLink.setAttribute('data-sent', 'false');
        alert('Activation code resent!');
    }, 5000);
});

Conclusion

This solution creates a user-friendly, fully functional 6-digit passcode system using plain JavaScript. It supports pasting, input validation, seamless navigation, and code verification, ensuring a smooth experience. Enhance it further by connecting the verification logic to your backend or adding animations for better visual feedback.

For more tips on web development, check out DailySandbox and sign up for our free newsletter to stay ahead of the curve!