0

I'm completely new to JavaScript. I'm trying to allow users to select certain criteria for the password they would like to generate. I've made it so that if the user selects yes to certain password criteria, it is concat into another empty array. How should I go about creating a for loop that utilizes Math.random and other means of shuffling content of an array to generate and spit out what they have selected based on length of password and character type selected by the user? I've been agonizing over this for days and I can not figure it out.

var selectedNumbers = window.confirm("Password should contain numbers?");
var selectedLowerCase = window.confirm("Password should contain lowercase letters?");
var selectedUpperCase = window.confirm("Password should uppercase letters?");
var selectedSpecial = window.confirm("Password should contain special characters?");
if (selectedNumbers === true) {
  characterOptionsList.concat(numbersList)
} else {
  console.log(false);
}

if (selectedLowerCase === true) {
  characterOptionsList.concat(lowerCaseList)
} else {
  console.log(false);
}

if (selectedUpperCase === true) {
  characterOptionsList.concat(upperCaseList)
} else {
  console.log(false);
}

if (selectedSpecial === true) {
  characterOptionsList.concat(specialList)
} else {
  console.log(false);
}

}

I've already attempted a for loop, but it does absolutely nothing.

function writePassword() {

  for (var i = 0; i > characterOptionsList.length; i++) {
    const newPassword = Math.floor((characterOptionsList.length - start) * Math.random())
    const randomArray = characterOptionsList.splice(randomPosition, 1)

    randomArray.push(characterOptionsList);

    return randomArray;

  }
  var password = generatePassword();
  var passwordText = document.querySelector("#password");

  passwordText.value = password

}
generateBtn.addEventListener("click", writePassword);

Here are the variables set for criteria arrays as well as the empty array they are to be concat inside of, if it's of any use to better understand what I'm trying to do.

var generateBtn = document.querySelector("#generate");
var numbersList = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",];
var lowerCaseList = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
var upperCaseList = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
var specialList = ["!", "@", "#", "$", "%", "^", "&", "*", "(", ")",];
var characterOptionsList = []
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • In the writePassword function what are characterOptionsList? Why you assign to constant in a loop? Where you use newPassword...? – Oussama Ben Ghorbel Sep 20 '22 at 18:35
  • 2
    There are many, many questions about how to randomly select items from arrays. Unfortunately, you've not provided a [mre] (with the HTML that goes along with your JavaScript), so it's hard to say what you're doing wrong exactly. – Heretic Monkey Sep 20 '22 at 18:41
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Sep 20 '22 at 20:20

1 Answers1

-2

If you know the length of the password, couldn't you just loop for the length of the password and append a character of a random index from the characterOptionsList? That would look something like this:

const passwordLen = 10
const characterOptionsList = ["A", "B", "C", "a", "b", "c", "0", "1", "2"] // for example

let password = ""
for (let i = 0; i < passwordLen; i++) {
  let randInx = Math.floor(characterOptionsList.length*Math.random())
  password += characterOptionsList[randInx]
}

You could also shuffle the characterOptionsList and then take a subset of the shuffled array as described in this answer:

const passwordLen = 5
const characterOptionsList = ["A", "B", "C", "a", "b", "c", "0", "1", "2"] // for example

const shuffled = characterOptionsList.sort(() => 0.5 - Math.random())

let password = shuffled.slice(0, passwordLen).join("")

console.log(password)

However, doing it like this would result in generating a password that has no duplicate characters. It would also require the password length to be less than the length of characterOptionsList.

Note that these answers won't yet guarantee that the generated password will have characters from all the different sets that the user chooses (numbers, lowercase, uppercase, special)! It only includes those in the set of possible characters to appear in the generated password.

Another thing: the concat method doesn't change the characterOptionsList in-place but rather returns a new array so it should be characterOptionsList = characterOptionsList.concat(numbersList). Same for the other concat calls.

Edit

If you want to ensure that the generated password includes at least one character from each selected set, you can do something like this:

let randomIndex = (max) => {
  return Math.floor(max*Math.random())
}

let addCharacterToRandomInx = (arr, c) => {
  while (true) {
    let randInx = randomIndex(arr.length)
    if (arr[randInx] === undefined) {
      arr[randInx] = c
      return
    }
  }
}

const passwordLen = 10

const numbersList = ["0", "1", "2"]
const lowercase = ["a", "b", "c"]
const uppercase = ["A", "B", "C"]
const special = ["!", "@", "#"]

let useNumbers = true
let useLowercase = true
let useUppercase = false
let useSpecial = true

const characterOptionsList = ["a", "b", "c", "0", "1", "2", "!", "@", "#"] // for example

let passwordArray = Array(passwordLen)

// Use addCharacterToRandomInx to make sure that the characters are not put in to the same index
if (useNumbers) addCharacterToRandomInx(passwordArray, numbersList[randomIndex(numbersList.length)])
if (useLowercase) addCharacterToRandomInx(passwordArray, lowercase[randomIndex(lowercase.length)])
if (useUppercase) addCharacterToRandomInx(passwordArray, uppercase[randomIndex(uppercase.length)])
if (useSpecial) addCharacterToRandomInx(passwordArray, special[randomIndex(special.length)])

for (let i = 0; i < passwordLen; i++) {
  if (passwordArray[i] !== undefined) continue
  passwordArray[i] = characterOptionsList[randomIndex(characterOptionsList.length)]
}

let password = passwordArray.join("")

console.log(password)

Note: the password length has to be more than the number of selected character sets

VOL
  • 279
  • 2
  • 9
  • I'm sure I could, but I'm so new to JavaScript that I don't know how to structure that into a for loop lmao If you could show a code snippet of what you are talking about, that would be super helpful! Thanks for the comment! – user20039792 Sep 20 '22 at 18:40
  • I added some examples – VOL Sep 20 '22 at 20:25