0

I'm making a course and one of the tasks is to generate four different passwords that should fill the four different paragraphs <p id="first"></p>, <p id="second"></p>, <p id="third"></p>, <p id="fourth"></p>

I have created a script that creates a password but somehow it doesn't print the first password. When I do console.log(password) it shows that creates a password on the console. But when I try to put first.textContent = password it shows nothing.

let chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "A", "B", "C", "D"]
let number = 10
let password = ""
let first = document.getElementById("first")
let second = document.getElementById("second")
let third = document.getElementById("third")
let fourth = document.getElementById("fourth")

function generate() {
  for (let i = 0; i < number; i++) {
    let passwordChar = Math.floor(Math.random() * chars.length)
    password += chars[passwordChar]
    return password
  }
}
first.textContent = password
<html>

<head>
  <link rel="stylesheet" href="index.css">
</head>

<body>
  <h1>Generate a random password</h1>
  <p id="description">Never use an insecure password again</p>
  <button onclick="generate()">Generate passwords</button>
  <p id="line"></p>
  <p id="first"></p>
  <p id="second"></p>
  <p id="third"></p>
  <p id="fourth"></p>
</body>

</html>

I'm also stuck to generate each time the function is running a new password and put it on the next paragraph. Like so:

first.textContent = password
second.textContent = password
third.textContent = password
fourth.textContent = password

Any help will be appreciated

TechySharnav
  • 4,869
  • 2
  • 11
  • 29
Zaesar
  • 352
  • 1
  • 3
  • 12
  • The `generate()` function is called when clicking on the button. Changed the numbers into chars. No effect – Zaesar Feb 10 '22 at 10:41

3 Answers3

0

Please pay attention to every single line of code you write. Every single line has a meaning!

  1. You don't need to keep track of the 'password' in an outer scope variable. You just need a local variable (also note the return part should be after the for loop:
function generate() {
    let pw = ''
    for (let i = 0; i < number; i++) {
        let passwordChar = Math.floor(Math.random() * chars.length)
        pw += chars[passwordChar]
    }    
    return pw
}
  1. You are not calling the generate():
first.textContent = generate()
second.textContent = generate()
third.textContent = generate()
fourth.textContent = generate()
Ergis
  • 1,105
  • 1
  • 7
  • 18
  • Thanks for your help. But I'm calling the generate function when clicking on the button – Zaesar Feb 10 '22 at 10:42
  • If such, you are setting the `first.textContent` before calling a `generate()` beforehand – Ergis Feb 10 '22 at 10:45
  • So it is calling before it is called with the button? If so, how do I change this? Appreciate – Zaesar Feb 10 '22 at 10:48
  • When I change to your code I get `!ReferenceError: pw is not defined`. when I write `let pw = ''` out of the function it works – Zaesar Feb 10 '22 at 10:52
0

It is generally not a good idea to use inline event handlers.

Here is a snippet using event delegation. For retrieving and filling certain elements, use a single identifier for them (here: a data attribute). Now you can loop the elements and fill them with your password values (forEach). In this snippet the passwords are generated using Array.map.

See also...

document.addEventListener(`click`, handle);

function handle(evt) {
// ↓ only do things if button#passGen is clicked
  if (evt.target.id === `passGen`) {
    return generate();
  }
}

function generate() {
  const chars = `0123456789abcdefghijk`;
  document.querySelectorAll(`[data-passgenerated]`)
  //                         ↑ retrieve all p[data-passgenerated]
  // ↓ Loop through the elements and fill them
  .forEach(elem =>  elem.textContent = [...Array(10)].map(v => 
    chars[Math.floor(Math.random() * chars.length)]).join(``)
);
}
<p data-passgenerated="1"></p>
<p data-passgenerated="2"></p>
<p data-passgenerated="3"></p>
<p data-passgenerated="4"></p>
<button id="passGen">Create passwords</button>
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • Thanks a lot for your comment! But I have to try to make it with the basic knowledge they have given to us on the course. We haven't done the code that you provide. Anyway, really appreciate – Zaesar Feb 10 '22 at 10:56
0

The main thing going wrong is that first.textContent = password is placed outside of generate(), so it will be set to the initial password value (empty string), but is never updated.

Without changing too much, I suggest splitting the code into two functions. One to generate a password, and one that assigns element contents to these randomly generated passwords.

function generatePassword() {
  const chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "A", "B", "C", "D"];
  let password = "";
  for (let i = 0; i < 10; i++) {
    const passwordChar = Math.floor(Math.random() * chars.length);
    password += chars[passwordChar];
  }
  // I've moved the return down, because you return after generating only 1 character
  return password;
}

function loadPasswords() {  
  document.getElementById("first").textContent = generatePassword();
  document.getElementById("second").textContent = generatePassword();
  document.getElementById("third").textContent = generatePassword();
  document.getElementById("fourth").textContent = generatePassword();
}
<h1>Generate a random password</h1>
<p id="description">Never use an insecure password again</p>
<button onclick="loadPasswords()">Generate passwords</button>
<p id="line"></p>
<p id="first"></p>
<p id="second"></p>
<p id="third"></p>
<p id="fourth"></p>

Like already stated by other answers, I would personally avoid using inline handlers and use addEventListener() instead.

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
  • Thank you so much. It helps me a lot to understand better Javascript. Is still a long way but appreciate the time you've taken to show me the way! – Zaesar Feb 10 '22 at 11:29