Incorrect result of loop - javascript

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>

Related

trying to link checkbox list with multiple functions using HTML & JAVASCRIPT

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>

need to append user data to array

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>

Keep html that is generated with javascript after laravel POST with old data

There are 2 fields that belong together price and size. Some products have more then 1 size, so the html offers a button to generate more fields. However if some validation fails the fields are gone and not populated anymore.
Here are the non generated html fields
<div class="col-md-6">
<label for="price" class="form-label">Prijs* </label>
<input type="text"
name="priceAndSize[price][0]"
class="form-control #if($errors->has('priceAndSize.price.*')) border-danger #endif"
id="price"
value="{{ old('priceAndSize.price[0]') }}">
</div>
<div class="col-md-6">
<label for="stock" class="form-label">Inhoud in ml</label>
<input type="text"
name="priceAndSize[size][0]"
class="form-control"
id="size"
value="{{ old('priceAndSize.size[0]') }}">
</div>
With a button to generate more fields
<input type="button" class="btn btn-info mt-3 text-white" onclick="addInput()"
value="Meerdere prijzen & inhoud"/>
the javascript to generate the fields:
counter = 1;
function addInput() {
// Input
const newInputPrice = document.createElement('input');
newInputPrice.id = 'price' + counter;
newInputPrice.name = 'priceAndSize[price][' + counter + ']';
newInputPrice.type = 'text';
newInputPrice.className = 'form-control';
const newInputSize = document.createElement('input');
newInputSize.id = 'size' + counter;
newInputSize.name = 'priceAndSize[size][' + counter + ']';
newInputSize.type = 'text';
newInputSize.className = 'form-control';
// Label
const labelPrice = document.createElement('label');
labelPrice.htmlFor = 'price' + counter;
labelPrice.innerHTML = 'Prijs* ';
labelPrice.className = 'form-label';
const labelSize = document.createElement('label');
labelSize.htmlFor = 'size' + counter;
labelSize.innerHTML = 'Inhoud* ';
labelSize.className = 'form-label';
// New boostrap div
const newDivPrice = document.createElement('div');
newDivPrice.className = 'col-md-6';
const newDivSize = document.createElement('div');
newDivSize.className = 'col-md-6';
// Add label and input to div
newDivPrice.appendChild(labelPrice);
newDivPrice.appendChild(newInputPrice);
newDivSize.appendChild(labelSize);
newDivSize.appendChild(newInputSize);
const currentDiv = document.getElementById("test");
currentDiv.appendChild(newDivPrice);
currentDiv.appendChild(newDivSize);
counter++;
}
You can try this in your blade.
$priceAndSize = Request::old('priceAndSize');
#if(count($priceAndSize[price]) > 0)
for (var i = 1; i <= {{count($priceAndSize[price])}}; i++) {
addInput();
}
#elseif(count($priceAndSize[size]) > 0)
for (var i = 1; i <= {{count($priceAndSize[size])}}; i++) {
addInput();
}
#endif

JavaScript - Password Generator (checkbox)

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.

How to show values from a .js file previously executed from a webpage to another webpage?

This is the webpage that will execute calculations in JS there are other personalityType I just didn't include them
<div class="question">
<div>40. It is easy for me to identify how I feel and why. </div>
<div> <input class="radiobutton" type="radio" name="m40" value="0" personalityType="intrapersonal"> Never <input class="radiobutton" type="radio" name="m40" value="1" personalityType="intrapersonal"> Rarely <input
class="radiobutton" type="radio" name="m40" value="2" personalityType="intrapersonal"> Often
<input class="radiobutton" type="radio" name="m40" value="3" personalityType="intrapersonal"> Always
</div>
<div class="question">
<div>35. English is/was one of my favorite subjects in school. </div>
<div> <input class="radiobutton" type="radio" name="m35" value="0" personalityType="verbal"> Never <input class="radiobutton" type="radio" name="m35" value="1" personalityType="verbal"> Rarely <input class="radiobutton"
type="radio" name="m35" value="2" personalityType="verbal">
Often
<input class="radiobutton" type="radio" name="m35" value="3" personalityType="verbal"> Always
</div>
<div>
<a class="myButton" onclick=calculateScores() href=results.html>Get Results</a>
</div>
This is the .js
var bodilyScore = 0;
var mathematicalScore = 0;
var naturalistScore = 0;
var interpersonalScore = 0;
var visualScore = 0;
var verbalScore = 0;
var intrapersonalScore = 0;
var musicalScore = 0;
function calculateScores() {
var button = document.getElementsByClassName("radiobutton");
var buttonLength = button.length;
musicalScore = 0;
bodilyScore = 0;
mathematicalScore = 0;
naturalistScore = 0;
interpersonalScore = 0;
visualScore = 0;
verbalScore = 0;
intrapersonalScore = 0;
for (var i = 0; i < buttonLength; i++) {
if (button[i].type === 'radio' && button[i].checked) {
var value = Number(button[i].value);
var type = button[i].getAttribute("personalityType");
switch (type) {
case "musical":
musicalScore += value;
break;
case "bodily":
bodilyScore += value;
break;
case "mathematical":
mathematicalScore += value;
break;
case "naturalist":
naturalistScore += value;
break;
case "interpersonal":
interpersonalScore += value;
break;
case "visual":
visualScore += value;
break;
case "verbal":
verbalScore += value;
break;
case "intrapersonal":
intrapersonalScore += value;
break;
}
}
}
showResults();
}
function showResults() {
console.log(musicalScore);
console.log(bodilyScore);
console.log(mathematicalScore);
console.log(naturalistScore);
console.log(interpersonalScore);
console.log(visualScore);
console.log(verbalScore);
console.log(intrapersonalScore);
document.getElementById('musicalResult').innerText = musicalScore;
document.getElementById('bodilyResult').innerText = bodilyScore;
document.getElementById('naturalistResult').innerText = naturalistScore;
document.getElementById('interpersonalResult').innerText = interpersonalScore;
document.getElementById('visualResult').innerText = visualScore;
document.getElementById('intrapersonalResult').innerText = intrapersonalScore;
document.getElementById('verbalResult').innerText = verbalScore;
document.getElementById('mathematicalResult').innerText = mathematicalScore;
}
I wanted to get the value of the 3 highest scores among musicalScore, verbalScore, etc.). after clicking the "Get Results" button and display it on another webpage. How could I also attach a text to the Score with the highest value to be displayed also?
If you want to pass your result to another page you can store them in LocalStorage.
highestResults = {mathematicalScore: 4, naturalistScore: 6, verbalScore: 5};
localStorage.setItem('calculationResults', highestResults);
And on result page.
localStorage.getItem('calculationResults');
If you want to add text to highest result:
document.getElementById('mathematicalResult').innerText = mathematicalScore + ' - highest result';

Categories