Password Generator: How to Generate Passwords Using JavaScript

Muhaymin Bin Mehmood

Muhaymin Bin Mehmood

· 5 min read
Password Generator: How to Generate Passwords Using JavaScript Banner image
Password Generator: How to Generate Passwords Using JavaScript Banner image

In this comprehensive guide, we'll walk through the creation of a password generator using JavaScript. This generator, designed to create secure passwords, will allow users to customize the length and complexity of their passwords, providing a secure means of generating unique credentials for various accounts. With the increasing number of online accounts, ensuring each one has a unique and strong password is crucial to protect your data in today's digital age.

Understanding the Structure

Before diving into the code, let's understand the structure of our password generator. We'll have several components:

  1. User Interface: HTML elements for user interaction, including sliders, checkboxes, and buttons.
  2. Password Generation Logic: JavaScript functions to generate random passwords based on user preferences.
  3. Event Listeners: Code to handle user interactions and generate passwords accordingly.

Now, let's dive into the detailed explanation of the JavaScript code:

1. Range Slider Properties

const sliderProps = {
	fill: "#0B1EDF",
	background: "rgba(255, 255, 255, 0.214)",
};

Explanation:

Range Slider Properties.

  • Fill: The color that sticks around while you move the slider.
  • background: Default Range Slider Background

2. Selecting Range Slider and Slider Value

const slider = document.querySelector(".range__slider");
const sliderValue = document.querySelector(".length__title");

Explanation:

  • Selects the range slider and the element displaying the slider value.

3. Applying Fill to Range Slider

slider.querySelector("input").addEventListener("input", event => {
    sliderValue.setAttribute("data-length", event.target.value);
    applyFill(event.target);
});

applyFill(slider.querySelector("input"));

function applyFill(slider) {
   const percentage = (100 * (slider.value - slider.min)) / (slider.max - slider.min);

	const bg = `linear-gradient(90deg, ${sliderProps.fill} ${percentage}%, ${sliderProps.background} ${percentage + 0.1}%)`;

	slider.style.background = bg;
	sliderValue.setAttribute("data-length", slider.value);
}

Explanation:

  • Adds an event listener to the range input to update the slider value display and apply fill effect when the slider value changes.
  • Calls the applyFill function to initially apply the fill.

4. Object of Random Functions

const randomFunc = {
    lower: getRandomLower,
    upper: getRandomUpper,
    number: getRandomNumber,
    symbol: getRandomSymbol,
};

Explanation:

  • Defines an object containing references to functions responsible for generating random characters for lowercase letters, uppercase letters, numbers, and symbols.

5. Secure Math Random Function

function secureMathRandom() {
    return window.crypto.getRandomValues(new Uint32Array(1))[0] / (Math.pow(2, 32) - 1);
}

Explanation:

  • Defines a function secureMathRandom that utilizes the window.crypto.getRandomValues method to generate a more secure random value compared to Math.random().

6. Generator Functions for Random Characters

function getRandomLower() {
	return String.fromCharCode(Math.floor(Math.random() * 26) + 97);
}
function getRandomUpper() {
	return String.fromCharCode(Math.floor(Math.random() * 26) + 65);
}
function getRandomNumber() {
	return String.fromCharCode(Math.floor(secureMathRandom() * 10) + 48);
}
function getRandomSymbol() {
	const symbols = '~!@#$%^&*()_+{}":?><;.,';
	return symbols[Math.floor(Math.random() * symbols.length)];
}

Explanation:

Functions responsible for generating random characters:

  • getRandomLower: Generates a random lowercase letter.
  • getRandomUpper: Generates a random uppercase letter.
  • getRandomNumber: Generates a random number.
  • getRandomSymbol: Generates a random symbol.

7. Selecting DOM Elements

const resultEl = document.getElementById("result");
const lengthEl = document.getElementById("slider");
const uppercaseEl = document.getElementById("uppercase");
const lowercaseEl = document.getElementById("lowercase");
const numberEl = document.getElementById("number");
const symbolEl = document.getElementById("symbol");
const generateBtn = document.getElementById("generate");
const copyBtn = document.getElementById("copy-btn");
const resultContainer = document.querySelector(".result");
const copyInfo = document.querySelector(".result__info.right");
const copiedInfo = document.querySelector(".result__info.left");

Explanation:

  • Selects various DOM elements necessary for the password generation and UI interaction.

8. Handling Copy Button Visibility

let generatedPassword = false;

let resultContainerBound = {
	left: resultContainer.getBoundingClientRect().left,
	top: resultContainer.getBoundingClientRect().top,
};

resultContainer.addEventListener("mousemove", e => {
	resultContainerBound = {
		left: resultContainer.getBoundingClientRect().left,
		top: resultContainer.getBoundingClientRect().top,
	};
	if(generatedPassword){
		copyBtn.style.opacity = '1';
		copyBtn.style.pointerEvents = 'all';
		copyBtn.style.setProperty("--x", `${e.x - resultContainerBound.left}px`);
		copyBtn.style.setProperty("--y", `${e.y - resultContainerBound.top}px`);
	}else{
		copyBtn.style.opacity = '0';
		copyBtn.style.pointerEvents = 'none';
	}
});
window.addEventListener("resize", e => {
	resultContainerBound = {
		left: resultContainer.getBoundingClientRect().left,
		top: resultContainer.getBoundingClientRect().top,
	};
});

Explanation:

  • Event listeners to manage the visibility and position of the copy button based on mouse movement and window resizing.

9. Copying Password to Clipboard

copyBtn.addEventListener("click", () => {
	const textarea = document.createElement("textarea");
	const password = resultEl.innerText;
	if (!password || password == "CLICK GENERATE") {
		return;
	}
	textarea.value = password;
	document.body.appendChild(textarea);
	textarea.select();
	document.execCommand("copy");
	textarea.remove();

	copyInfo.style.transform = "translateY(200%)";
	copyInfo.style.opacity = "0";
	copiedInfo.style.transform = "translateY(0%)";
	copiedInfo.style.opacity = "0.75";
});

Explanation:

  • Adds an event listener to the copy button to copy the generated password to the clipboard when clicked.

10. Generating Password

generateBtn.addEventListener("click", () => {
	const length = +lengthEl.value;
	const hasLower = lowercaseEl.checked;
	const hasUpper = uppercaseEl.checked;
	const hasNumber = numberEl.checked;
	const hasSymbol = symbolEl.checked;
	generatedPassword = true;
	resultEl.innerText = generatePassword(length, hasLower, hasUpper, hasNumber, hasSymbol);
	copyInfo.style.transform = "translateY(0%)";
	copyInfo.style.opacity = "0.75";
	copiedInfo.style.transform = "translateY(200%)";
	copiedInfo.style.opacity = "0";
});

Explanation:

  • Adds an event listener to the generate button to generate a password based on user-selected options when clicked.

11. Helper Function for Checkbox State

function disableOnlyCheckbox(){
	let totalChecked = [uppercaseEl, lowercaseEl, numberEl, symbolEl].filter(el => el.checked)
	totalChecked.forEach(el => {
		if(totalChecked.length == 1){
			el.disabled = true;
		}else{
			el.disabled = false;
		}
	})
}

Explanation:

  • Function to handle the state of checkboxes to ensure that at least one checkbox is selected, and disables the last checkbox if only one is checked.

12. Event Listeners for Checkbox Click

[uppercaseEl, lowercaseEl, numberEl, symbolEl].forEach(el => {
    el.addEventListener('click', () => {
        disableOnlyCheckbox()
    })
});

Explanation:

  • Adds event listeners to checkboxes to call the disableOnlyCheckbox function when clicked.

13. Event Listeners for Checkbox Click

function generatePassword(length, lower, upper, number, symbol) {
    let generatedPassword = "";
    const typesCount = lower + upper + number + symbol;
    const typesArr = [{ lower }, { upper }, { number }, { symbol }].filter(item => Object.values(item)[0]);
    if (typesCount === 0) {
        return "";
    }
    for (let i = 0; i < length; i++) { 
        typesArr.forEach(type => {
            const funcName = Object.keys(type)[0]; 
            generatedPassword += randomFunc[funcName](); 
        });
    }
    return generatedPassword.slice(0, length).split('').sort(() => Math.random() - 0.5).join('');
}

Explanation:

  • The generatePassword function takes parameters for length and boolean values representing whether to include lowercase letters, uppercase letters, numbers, and symbols in the generated password.
  • It initializes an empty string generatedPassword to store the generated password.
  • It calculates the typesCount by adding the boolean values of selected character types.
  • Based on the selected character types, it creates an array typesArr containing objects representing the selected types.
  • If no character types are selected (i.e., typesCount === 0), it returns an empty string.
  • It then loops length times to generate characters for the password.
  • Within the loop, it iterates over the typesArr array and appends a random character of each selected type to the generatedPassword.
  • After generating the password, it slices the password to the specified length, shuffles the characters randomly, and returns the final generated password.

For the full code and a live demo, visit the JSFiddle link.

Muhaymin Bin Mehmood

About Muhaymin Bin Mehmood

I am a Front-End Developer specializing in Frontend at Dvago.pk.

Copyright © 2024 Mbloging. All rights reserved.