I am working for an assignment about a password generator. Here is my HTML and JavaScript. When I click the checkbox for number and symbol, the result returns a password including "undefined". I guess the issue is from my if-else statement for checkbox status. What the result I expected is that whichever I click , the result does not include any letter of "undefined". Could someone help me with this issue? Thank you!
const btn = document.querySelector(".btn")
function getChar(num, char) {
if (document.querySelector("input[name=" + num + "]").checked) {
return char
}
}
btn.addEventListener("click", e => {
if (!document.querySelector("input[name=en]").checked && !document.querySelector("input[name=num]").checked && !document.querySelector("input[name=sym]").checked) {
return
}
let password = ""
let alphabet = "abcdefghijklmnopqrstuvwxyz"
let number = "0123456789"
let symbol = "!##$%^&*+="
password += getChar("en", alphabet)
password += getChar("num", number)
password += getChar("sym", symbol)
let result = ""
for (let i = 0; i < 10; i++) {
let num = Math.floor(Math.random() * password.length)
result += password[num]
}
console.log(result)
document.querySelector(".result").innerHTML = result
})
<div class="container">
<div class="english">
<label for="en">English letter</label>
<input type="checkbox" name="en">
</div>
<div class="number">
<label for="num">Number</label>
<input type="checkbox" name="num">
</div>
<div class="symbol">
<label for="sym">Symbol</label>
<input type="checkbox" name="sym">
</div>
<button class="btn">Generate</button>
<div class="result"></div>
</div>
The problem was that the getChar function, returns undefined if the check-box isn't checked. The desired functionality can be achieved by this modifications:
const btn = document.querySelector(".btn")
function getChar(num) {
return document.querySelector("input[name=" + num + "]").checked
}
btn.addEventListener("click", e => {
if (!document.querySelector("input[name=en]").checked && !document.querySelector("input[name=num]").checked && !document.querySelector("input[name=sym]").checked) {
return
}
let password = ""
let alphabet = "abcdefghijklmnopqrstuvwxyz"
let number = "0123456789"
let symbol = "!##$%^&*+="
if (getChar("en")) password += alphabet
if (getChar("num")) password += number
if (getChar("sym")) password += symbol
let result = ""
for (let i = 0; i < 10; i++) {
let num = Math.floor(Math.random() * password.length)
result += password[num]
}
console.log(result)
document.querySelector(".result").innerHTML = result
})
<div class="container">
<div class="english">
<label for="en">English letter</label>
<input type="checkbox" name="en">
</div>
<div class="number">
<label for="num">Number</label>
<input type="checkbox" name="num">
</div>
<div class="symbol">
<label for="sym">Symbol</label>
<input type="checkbox" name="sym">
</div>
<button class="btn">Generate</button>
<div class="result"></div>
</div>
When a checkbox is unchecked, it's value is undefined.
Because you return the value every time when you add new characters to the password variable, you add 'undefined'.
Just add a else statement that returns an empty string.
Related
I study Java Script and faced the problem that during looping the result of last cycle is inserted not at the last but at first.
My Code:
//Determine annuity
const annuity = document.querySelector('#annuityType');
let payment = document.querySelector('#cashFlowType');
function showAnnuity() {
payment.innerHTML = ``;
payment = document.querySelector('#cashFlowType');
payment.innerHTML = `<label for="annuity">Сума ануїтету </label><input id="annuity" name="annuity" type="text"><br><br>`;
}
annuity.onclick = showAnnuity;
//Determine different cash flows
const different = document.querySelector('#differentType');
function showDifferentType() {
payment.innerHTML = ``;
payment = document.querySelector('#cashFlowPeriods');
let newPayment;
for (let i = 1; i <= document.querySelector('#period').value; i++) {
if (i == 1) {
newPayment = document.querySelector('#cashFlowOne');
newPayment.innerHTML = `<label for="diffCashFlow">Income for period <span id="periodDiff">1 </span></label><input id="diffCashFlow" name="differentCashFlow" type="text"><br><br>`;
} else {
let np = newPayment.cloneNode(true);
np.id = i;
document.querySelector('#periodDiff').innerHTML = i + " ";
payment.append(np);
}
}
}
different.onclick = showDifferentType;
<div>
<label for="period">Строк проекту (у роках)</label>
<input id="period" name="period" type="text">
</div>
<div>
<p>What kind of payment?</p>
<label for="annuityType">Annuity</label>
<input id="annuityType" name="cashFlowType" type="radio">
<label for="differentType">Different payments</label>
<input id="differentType" name="cashFlowType" type="radio">
</div><br>
<div id="cashFlowType"></div>
<div id="cashFlowPeriods">
<div id="cashFlowOne"><span id="periodDiff"></span></div>
</div>
For example, when I insert 5 into input "period", the sequence of results of loop is next:
Income for period 5
Income for period 1
Income for period 2
Income for period 3
Income for period 4
I tried to researched the reason but didn't find it. I will be grateful for any help.
You need to assign the innerHTML of the cloned node, not the original node after you cloned it.
Since IDs shouldn't be repeated, change id="periodDiff" to class="periodDiff".
//Determine annuity
const annuity = document.querySelector('#annuityType');
let payment = document.querySelector('#cashFlowType');
function showAnnuity() {
payment.innerHTML = ``;
payment = document.querySelector('#cashFlowType');
payment.innerHTML = `<label for="annuity">Сума ануїтету </label><input id="annuity" name="annuity" type="text"><br><br>`;
}
annuity.onclick = showAnnuity;
//Determine different cash flows
const different = document.querySelector('#differentType');
function showDifferentType() {
payment.innerHTML = ``;
payment = document.querySelector('#cashFlowPeriods');
let newPayment;
for (let i = 1; i <= document.querySelector('#period').value; i++) {
if (i == 1) {
newPayment = document.querySelector('#cashFlowOne');
newPayment.innerHTML = `<label for="diffCashFlow">Income for period <span class="periodDiff">1 </span></label><input class="diffCashFlow" name="differentCashFlow" type="text"><br><br>`;
} else {
let np = newPayment.cloneNode(true);
np.id = i;
np.querySelector(".periodDiff").innerHTML = i + " ";
payment.append(np);
}
}
}
different.onclick = showDifferentType;
<div>
<label for="period">Строк проекту (у роках)</label>
<input id="period" name="period" type="text">
</div>
<div>
<p>What kind of payment?</p>
<label for="annuityType">Annuity</label>
<input id="annuityType" name="cashFlowType" type="radio">
<label for="differentType">Different payments</label>
<input id="differentType" name="cashFlowType" type="radio">
</div><br>
<div id="cashFlowType"></div>
<div id="cashFlowPeriods">
<div id="cashFlowOne"><span id="periodDiff"></span></div>
</div>
you need to create elements using document.createElement instead of relying on building it using .innerHTML which can be risky if misused.
//Determine annuity
const annuity = document.querySelector('#annuityType');
let payment = document.querySelector('#cashFlowType');
function showAnnuity(){
payment.innerHTML = ``;
payment = document.querySelector('#cashFlowType');
payment.innerHTML = `<label for="annuity">Сума ануїтету </label><input id="annuity" name="annuity" type="text"><br><br>`;
}
annuity.onclick = showAnnuity;
//Determine different cash flows
const different = document.querySelector('#differentType');
function showDifferentType(){
payment.innerHTML = ``;
payment = document.querySelector('#cashFlowPeriods');
let newPayment;
let html = '';
for(let i = 1; i <= document.querySelector('#period').value; i++){
let label = document.createElement('label');
let input = document.createElement('input');
let br = document.createElement('br');
input.id = `periodDiff${i}`;
label.htmlFor = input.id;
label.innerText = `Income for period ${i} `;
payment.append(label);
payment.append(input);
payment.append(br);
}
}
different.onclick = showDifferentType;
<div>
<label for="period">Строк проекту (у роках)</label>
<input id="period" name="period" type="text">
</div>
<div>
<p>What kind of payment?</p>
<label for="annuityType">Annuity</label>
<input id="annuityType" name="cashFlowType" type="radio">
<label for="differentType">Different payments</label>
<input id="differentType" name="cashFlowType" type="radio">
</div><br>
<div id="cashFlowType"></div>
<div id="cashFlowPeriods"><div id="cashFlowOne"> <span id="periodDiff"></span></div></div>
<div>
my code calculates the AVG or MAX of an input set of numbers, I want the user to check on a checkbox list that contains AVG and MAX for desired output but I couldn't figure out doing it.
if I put an input of "2,4" without check listing the output is both AVG and MAX which is 3 4, I tried to checklist for only AVG or MAX outcome but it didn't work.
I have checked both function calculateAVG() & calculateMAX() and they produce correct output
function proccesFloat(flt) {
var splitFloat = flt.split(",");
for (x in splitFloat) {
splitFloat[x] = parseFloat(splitFloat[x]);
}
return splitFloat;
}
function calculateAVG(setNum) {
let total = 0;
var numInput = document.getElementById("setNum").value;
var result = 0;
var avg = proccesFloat(numInput);
for (let i = 0; i < avg.length; i++) {
total += avg[i];
}
result = total / avg.length;
document.getElementById('outputAVG').innerHTML = result;
}
function calculateMAX(setNum) {
var numInput = document.getElementById("setNum").value;
var numarry = proccesFloat(numInput);
var max = 0;
for (let i = 0; i < numarry.length; i++) {
if (numarry[i] > max) {
max = numarry[i];
}
}
document.getElementById('outputMAX').innerHTML = max;
}
function calculate() {
var checkBox = document.getElementsByTagName("check");
if (checkBox[0].checked) {
calculateAVG(document.getElementById("setNum"));
}
if (checkBox[0].checked) {
calculateMAX(document.getElementById("setNum"));
} {
alert('please choose formula')
return false;
}
}
<header>
<input type="Numbers" id="setNum" placeholder="Enter Set of Numbers">
<br>
<button onclick="calculate()" id="btn1">calculate</button>
<output id="outputAVG"></output>
<output id="outputMAX"></output>
<form method="post">
<fieldset>
<legend>Formula To Calculate?</legend>
<input type="checkbox" id="avg" name="check" onclick="calculate()">AVG<br>
<input type="checkbox" id="max" name="check" onclick="calculate()">MAX<br>
<br>
</fieldset>
</form>
</header>
Count the checked and then look at the IDs.
I also suggest you wrap in a form and use the submit event
I made a few more changes to simplify the code
Let the functions do one thing and use the event to bring them together
const proccesFloat = flt => flt.split(",").map(fl => +fl); // cast to float
const calculateAVG = setNum => {
const arr = proccesFloat(setNum);
const total = arr.reduce((a, b) => a + b)
return total / arr.length;
}
const calculateMAX = setNum => Math.max(...proccesFloat(setNum));
document.getElementById("calcForm").addEventListener("submit", function(e) {
e.preventDefault(); // stop submission
const chks = document.querySelectorAll("[name=check]:checked")
if (chks.length === 0) {
alert('please choose formula')
return
}
if (document.getElementById("avg").checked) {
document.getElementById('outputAVG').innerHTML = calculateAVG(document.getElementById("setNum").value);
}
if (document.getElementById("max").checked) {
document.getElementById('outputMAX').innerHTML = calculateMAX(document.getElementById("setNum").value);
}
})
<header>
<form id="calcForm">
<input type="Numbers" id="setNum" placeholder="Enter Set of Numbers">
<br>
<button type="submit">calculate</button>
<output id="outputAVG"></output>
<output id="outputMAX"></output>
<fieldset>
<legend>Formula To Calculate?</legend>
<input type="checkbox" id="avg" name="check">AVG<br>
<input type="checkbox" id="max" name="check">MAX<br>
<br>
</fieldset>
</form>
</header>
my original question got answered but I realize that every time I try to push user data in the arrays it wouldn't allow me to do is there any another to append data to arrays or is the push method the only way. or should i create a new array................................................................
"use strict"
const names = ["Ben", "Joel", "Judy", "Anne"];
const scores = [88, 98, 77, 88];
const $ = selector => document.querySelector(selector);
const addScore = () => {
// get user entries
const name = $("#name").value;
const score = parseInt($("#score").value);
let isValid = true;
// check entries for validity
if (name == "") {
$("#name").nextElementSibling.textContent = "This field is required.";
isValid = false;
} else {
$("#name").nextElementSibling.textContent = "";
}
if (isNaN(score) || score < 0 || score > 100) {
$("#score").nextElementSibling.textContent = "You must enter a valid score.";
isValid = false;
} else {
$("#score").nextElementSibling.textContent = "";
}
if (isValid) {
names.push("#name");
scores.push("#score");
names[names.length] = name;
scores[scores.length] = score;
$("#name").value = "";
$("#score").value = "";
}
$("#name").focus();
};
// display scores
const displayScores = () => {
for (let i = 0; i < names.length; i++) {
document.getElementById("scores_display").textContent += names[i] + " = " +
scores[i] +
"\n";
}
};
document.addEventListener("DOMContentLoaded", () => {
$("#add").addEventListener("click", addScore);
$("#display_scores").addEventListener("click", displayScores())
$("#name").focus();
});
<main>
<h1>Use a Test Score array</h1>
<div>
<label for="name">Name:</label>
<input type="text" id="name">
<span></span>
</div>
<div>
<label for="score">Score:</label>
<input type="text" id="score">
<span></span>
</div>
<div>
<label> </label>
<input type="button" id="add" value="Add to Array">
<input type="button" id="display_scores" value="Display Scores">
</div>
<div>
<textarea id="scores_display"></textarea>
</div>
</main>
All my previous notes were incorrect. Your adhoc $ const threw me off! My apologies.
The issue was you weren't calling displayScores() after updating the array. Plus, I added a line to that function to clear the existing text before looping through your data.
"use strict"
const names = ["Ben", "Joel", "Judy", "Anne"];
const scores = [88, 98, 77, 88];
const $ = selector => document.querySelector(selector);
const addScore = () => {
// get user entries
const name = $("#name").value;
const score = parseInt($("#score").value);
let isValid = true;
// check entries for validity
if (name == "") {
$("#name").nextElementSibling.textContent = "This field is required.";
isValid = false;
} else {
$("#name").nextElementSibling.textContent = "";
}
if (isNaN(score) || score < 0 || score > 100) {
$("#score").nextElementSibling.textContent = "You must enter a valid score.";
isValid = false;
} else {
$("#score").nextElementSibling.textContent = "";
}
if (isValid) {
names.push("#name");
scores.push("#score");
names[names.length] = name;
scores[scores.length] = score;
$("#name").value = "";
$("#score").value = "";
// add to the textarea
displayScores()
}
$("#name").focus();
};
// display scores
const displayScores = () => {
document.getElementById("scores_display").textContent = "";
for (let i = 0; i < names.length; i++) {
document.getElementById("scores_display").textContent += names[i] + " = " +
scores[i] +
"\n";
}
};
document.addEventListener("DOMContentLoaded", () => {
$("#add").addEventListener("click", addScore);
$("#display_scores").addEventListener("click", displayScores())
$("#name").focus();
});
<main>
<h1>Use a Test Score array</h1>
<div>
<label for="name">Name:</label>
<input type="text" id="name">
<span></span>
</div>
<div>
<label for="score">Score:</label>
<input type="text" id="score">
<span></span>
</div>
<div>
<label> </label>
<input type="button" id="add" value="Add to Array">
<input type="button" id="display_scores" value="Display Scores">
</div>
<div>
<textarea rows="6" id="scores_display"></textarea>
</div>
</main>
I have created an input form in html and trying to get the value of this input field using JavaScript.
When I alert it, to check if it works, it returns an empty value. The code is below. What could be the problem?
var num1 = document.getElementById('numb1').value;
var num2 = document.getElementById('numb2').value;
var button = document.getElementsByTagName('button');
var show = document.getElementById('shows');
for (let i = 0; i < button.length; i++) {
if(button[i].id == 'plus'){
button[i].onclick = function (){
var a = num1 + num2;
alert(a);
}
}
}
<div class="container">
<div class="set">
<input type="text" id="numb1" placeholder="enter a number" >
<input type="text" id="numb2" placeholder="enter a number">
<div class="buttons">
<button id="plus">+</button>
<button id="min">-</button>
<button id="mult">*</button>
<button id="div">/</button>
</div>
<div class="show" id="shows"></div>
</div>
</div>
This because you have kept following lines outside the callback function:
var num1 = document.getElementById('numb1').value;
var num2 = document.getElementById('numb2').value;
So, num1 and num2 are initialized only once i.e. at page load-time. At this time both (num1 and num2) having empty value. Hence it not being initialized every time and showing and empty value.
Note:
Consider to parse input text into numeric values using parseInt() or parseFloat()
You should keep your JavaScript code in <script> tag.
Following is corrected code snippet:
var button = document.getElementsByTagName('button');
var show = document.getElementById('shows');
for (let i = 0; i < button.length; i++) {
if(button[i].id == 'plus'){
button[i].onclick = function (){
var num1 = document.getElementById('numb1').value;
var num2 = document.getElementById('numb2').value;
var a = parseFloat(num1 )+ parseFloat(num2);
alert(a);
}
}
}
<div class="container">
<div class="set">
<input type="text" id="numb1" placeholder="enter a number" >
<input type="text" id="numb2" placeholder="enter a number">
<div class="buttons">
<button id="plus">+</button>
<button id="min">-</button>
<button id="mult">*</button>
<button id="div">/</button>
</div>
<div class="show" id="shows"></div>
</div>
</div>
You need to get the value of the inputs when the button is clicked, not when the page loads.
var button = document.getElementsByTagName('button');
var show = document.getElementById('shows');
for (let i = 0; i < button.length; i++) {
if(button[i].id == 'plus'){
button[i].onclick = function (){
var num1 = parseFloat(document.getElementById('numb1').value);
var num2 = parseFloat(document.getElementById('numb2').value);
var a = num1 + num2;
alert(a);
}
}
}
The above code will get the value of the inputs when the button is clicked. I also presumed you would want the values converting to float, if this is not the case then remove the parseFloat function to make it:
var num1 = document.getElementById('numb1').value;
var num2 = document.getElementById('numb2').value;
I have a for loop to get multiple outputs from an array. The currencyType[type] is used to pre-pend the proper letters to match the DIV ID in the HTML.
for(let type = 0; type <= currencyType.length; type++) {
// This grabs the number from XRPUSDVAL + XRPUSDAMT
let node = document.getElementById(currencyType[type].innerHTML+"USDVAL").textContent * document.getElementById(currencyType[type].innerHTML+"USDAMT").value;
let total = node.toFixed(2);
console.log(total)
}
I get 2 values of the total inside my console with the statement above that are dynamic numbers.
65704.50
99.91
However when I add a statement to try to output it to a DIV ID on my HTML, The console then only shows the result of 1 of the outputs
for(let type = 0; type <= currencyType.length; type++) {
// This grabs the number from XRPUSDVAL + XRPUSDAMT
let node = document.getElementById(currencyType[type].innerHTML+"USDVAL").textContent * document.getElementById(currencyType[type].innerHTML+"USDAMT").value;
let total = node.toFixed(2);
console.log(total)
document.getElementById(currencyType[type]+"USDTOTAL").innerHTML = total; // <------ Added This Statement
}
Here is the section of the HTML as well where the Javascript interacts with
<div class="container">
<div class="row">
<div class="col-sm-4 pbf-crypto-container">
<form method="POST" action="/users/currencies/68">
<h3 class="pbfCurrencyType">ETH</h3>
<input class="form-control-lg" id="ETHUSDAMT" name="amount" type="text" value="75">
<h3>Market Value: ($)</h3>
<div id="ETHUSDVAL"></div>
<h3>Total Value: ($)</h3>
<div id="ETHUSDTOTAL"></div>
<hr>
<input class="btn btn-primary" id="pbf-update" type="submit" value="Update">
<button class="btn btn-primary" id="pbf-refresh">Refresh</button>
</form>
</div>
<div class="col-sm-4 pbf-crypto-container">
<form method="POST" action="/users/currencies/60">
<h3 class="pbfCurrencyType">XRP</h3>
<input class="form-control-lg" id="XRPUSDAMT" name="amount" type="text" value="100">
<h3>Market Value: ($)</h3>
<div id="XRPUSDVAL"></div>
<h3>Total Value: ($)</h3>
<div id="XRPUSDTOTAL"></div>
<hr>
<input class="btn btn-primary" id="pbf-update" type="submit" value="Update">
<button class="btn btn-primary" id="pbf-refresh">Refresh</button>
</form>
</div>
</div>
</div>
I was wondering if someone can show me the proper way so that within my for loop it will be able to insert the total's into the section of my DIV that I specified. I am not sure what I am doing wrong here. Any help would be much appreciated. Thank you.
This line seems to be wrong
document.getElementById(currencyType[type]+"USDTOTAL").innerHTML = total;
You need to append USDTOTAL to currencyType[type].innerHTML like earlier in the same loop.
Make it
document.getElementById(currencyType[type].innerHTML +"USDTOTAL").innerHTML = total;
Or refactor the code
for(let type = 0; type <= currencyType.length; type++)
{
let prefix = currencyType[type].innerHTML ;
let node = document.getElementById( prefix +"USDVAL").textContent * document.getElementById( prefix +"USDAMT").value;
let total = node.toFixed(2);
console.log(total)
document.getElementById( prefix + "USDTOTAL").innerHTML = total;
}
try to append the results:
for(let type = 0; type <= currencyType.length; type++) {
// This grabs the number from XRPUSDVAL + XRPUSDAMT
let node = document.getElementById(currencyType[type].innerHTML+"USDVAL").textContent * document.getElementById(currencyType[type].innerHTML+"USDAMT").value;
let total = node.toFixed(2);
console.log(total)
document.getElementById(currencyType[type]+"USDTOTAL").innerHTML += total; // <------ Added This Statement
}
I think that you can improve a lite bit more you code
from here:
for(let type = 0; type <= currencyType.length; type++)
{
let prefix = currencyType[type].innerHTML ;
let node = document.getElementById( prefix +"USDVAL").textContent * document.getElementById( prefix +"USDAMT").value;
let total = node.toFixed(2);
console.log(total)
document.getElementById( prefix + "USDTOTAL").innerHTML = total;
}
to here:
currencyType.forEach(currency => {
const prefix = currency.innerHTML;
const node = document.getElementById(`${prefix}USDVAL`).textContent * document.getElementById(`${prefix}USDAMT`).value;
const total = node.toFixed(2);
document.getElementById(`${prefix}USDTOTAL`).innerHTML = total;
});