How Do I retrieve values from an appended placeholder with ID? - javascript

So I made a button that creates an input placeholder every time it is clicked (limited to 4). The problem is, I am using post method, and doing .value in my code returns a TypeError, but not the default placeholders (eg: m1k1). The IDs are created, and they're similar to the default with the exception of a number that is generated in a for loop.
When I type in values in just the default placeholders, everything is fine.
Two elements
let m1k1 = document.querySelector('#mon1wk1')
let m1k2 = document.querySelector('#mon1wk2')
eventListener
let num = 1
function addWeek(e) {
e.preventDefault()
num++
let mkInput = document.createElement('input')
let forma = document.querySelector('#forma')
mkInput.placeholder = " "
mkInput.id = 'mon1wk' + num
mkInput.type = 'text'
forma.append(mkInput)
if (num === 4) {
addwk1.disabled = true;
Where values get stored into an object
pushMonths.firstMonth.Week1 = m1k1.value,
pushMonths.firstMonth.Week2 = m1k2.value,
Any help is appreciated

In the OP code the num equals 1, so when the id is assigned to a new <input> when the user clicks the <button>, the first <input> is assigned id="mon1wk1" and the second <input> is assigned id="mon1wk2". So now there's 2 pairs of <input> sharing the same id which is invalid plus the duplicates cannot be found by id since the browser quits searching as soon as it finds the first id, which explains why the static <input>s always worked.
In the example below, the object follows the following pattern:
Figure I
const obj = {
mw: [2, 1], // [2nd month, 1st week]
mon1: { // Each mon* object can have up to 4 wk* properties
wk1: mon1wk1.value,
⇓⇓⇓
wk4: mon1wk4.value
},
mon2: {
wk1: mon2wk1.value
}
};
Details are commented in example
// Reference <form>
const frm = document.forms.forma;
/**
* #param {object} obj - Used to keep data
* #param {array} obj.mw - Keeps count of current
* month at mw[0] and week at mw[1]
* #param {object} obj.mon* - Month holds 4 weeks
* #param {any} obj.wk* - Week holds associated
* <input> value
*/
const obj = {
mw: [1, 2],
mon1: {
wk1: 5,
wk2: 4
}
};
let m = obj.mw[0];
let w = obj.mw[1];
// Bind submit event to <form>
frm.onsubmit = addWeek;
function addWeek(e) {
// Stop <form> from killing page
e.preventDefault();
// Build new <input>
let mk = document.createElement('input');
mk.type = 'text';
frm.append(mk);
/*
Incerment 'w'
If 'w' is greater than 4...
...add a new 'mon*' object and assign it a new
'w'
*//*
Otherwise assign a new property to current 'mon*'
Assign id to new <input> with this pattern:
`mon${m}wk${w}`
*/
++w;
if (w > 4) {
++m;
w = 1;
obj['mon' + m] = {
['wk' + w]: 0
};
obj.mw[0] = m;
obj.mw[1] = 1;
} else {
obj['mon' + m]['wk' + w] = 0;
obj.mw[1] += 1;
}
mk.id = 'mon' + m + 'wk' + w;
console.log(obj);
}
// Bind input event to <form>
frm.oninput = saveData;
/*
When a user inputs a value into an <input>, assign
the value to the associated property of obj.
The value is coerced into a number: +mk.value
Remove the '+' if you want string instead.
*/
function saveData(e) {
const mk = e.target;
let id = mk.id;
obj[id.slice(0, 4)][id.slice(4)] = +mk.value;
console.log(obj);
}
form {
display: flex;
}
button,
input {
display: inline-block;
}
<form id='forma'>
<button id='addWk'>Add Week</button><br><hr>
<input id='mon1wk1' value='5'>
<input id='mon1wk2' value='4'>
</form>

Related

calculating an equation given a certain input from a user with JavaScript

JavaScript newbie here.
I am tasked with calculating a user's monthly payment by using a given equation. I am having trouble with getting the values from the user.
const loanAmount = document.getElementById('loan-amount');
const loanYears = document.getElementById('loan-years');
const loanRate = document.getElementById('loan-Rate');
const span = document.querySelector('span');
const form = document.getElementById("calc-form");
form.addEventListener("submit", function (e) {
e.preventDefault();
console.log('hello')
makeLogo();
});
function makeLogo(loanAmount, loanYears, loanRate) {
const principle = loanAmount.value
const n = loanYears.value * 12;
const i = loanRate.value / 12;
const monthylPayment = (principle* i)/1-(1+ i)** -(n);
span.innerText = monthylPayment;
}
This is what I have so far and am getting an error for the variables in the makeLogo function.
It's a good idea to separate your inputs, calculations and rendering into separate functions. try to keep functions as simple as possible.
You will need to re-evaluate your monthly cost calculator, but here is a working example which takes input, calculates and then renders into form fields.
document.getElementById("calc-form").addEventListener('submit', (e) => {
e.preventDefault();
var loanAmount = document.getElementById('loan-amount').value;
console.log(loanAmount);
var loanYears = document.getElementById('loan-years').value;
var loanRate = document.getElementById('loan-rate').value;
var monthlyPayment = makeLogo( loanAmount, loanYears, loanRate );
console.log(monthlyPayment);
// the monthly has now been calculated, simply put it where you'd like
var calculated = document.getElementById('calculated');
calculated.value = monthlyPayment;
var totalRepayment = document.getElementById('totalRepayment');
totalRepayment.value = monthlyPayment * ( loanYears * 12 );
} );
function makeLogo( principle, loanYears, loanRate) {
var n = loanYears * 12;
var i = loanRate / 12;
var result = ( principle * i) / 1 - ( 1 + i )**-( n );
return result;
}
<html>
<form action='submit' id ='calc-form'>
Loan Amount:<input id ='loan-amount'></input><BR/>
Loan Years:<input id='loan-years'></input><BR/>
Loan Rate:<input id='loan-rate'></input><BR/>
<input type='submit'>
</form>
<span id='span-output'>
Monthly Payment :<input id='calculated' readonly><BR/>
Total Re-Payment :<input id='totalRepayment' readonly>
</span>
</html>
The error you are seeing is likely because the makeLogo function is trying to access the value property of the loanAmount, loanYears, and loanRate variables. Still, they are DOM elements and not their values.
You can fix this by accessing the value property of the DOM elements before passing them to the function like so:
form.addEventListener("submit", function (e) {
e.preventDefault();
console.log('hello')
const principle = loanAmount.value;
const n = loanYears.value * 12;
const i = loanRate.value / 12;
makeLogo(principle, n, i);
});
function makeLogo(principle, n, i) {
const monthylPayment = (principle* i)/1-(1+ i)** -(n);
span.innerText = monthylPayment;
}
This way, the makeLogo function receives the values of the input fields as arguments and can perform the calculation correctly.
Also, make sure that you are getting the right input from the user by checking the value of each element by doing the following:
console.log(loanAmount.value,loanYears.value,loanRate.value)
and check if they are the values that you are expecting.

How does modifying an array changes another array in JS

I want someone to help me understand how does changing the item array changes the orderList array in the function below?
The function below is used to increment and decrement the quantity of the order
using "+" and "-" buttons, if the action is "+" then add 1 to quantity else minus 1 to quantity
const [orderItems, setOrderItems] = React.useState([])
const editOrder = (action, menuId, price) => {
let orderList = orderItems.slice()
let item = orderList.filter(a => a.menuId == menuId)
if(action == "+"){
if(item.length > 0)
let newQty = item[0].qty + 1
item[0].qty = newQty
item[0].total = item[0] * price
} else {
const newItem = {
menuId: menuId,
qty: 1,
price: price,
total: price
}
orderList.push(newItem)
}
setOrderItems(orderList)
} else {
if(item.length > 0) {
if (item[0].qty > 0){
let newQty = item[0].qty - 1
item[0].qty = newQty
item[0].total = newQty * price
}
}
setOrderItems(orderList)
}
}
In JS when you assign a value of object type (e.g. object literal, array, functions) to a variable say x, basically what gets assigned to x is a reference to the original value.
If I have
let a = {a: 123}; // _a_ is object
let b = a; // Now _b_ has a reference to it
b.a = 312; // Essentially here we are modifying _a_
console.log(a.a)
You see we managed to change a via b. Same thing can happen with arrays;
let a = [{a: 123}]; // Array is also object type
let b = a; // Same logic applies here, _b_ points to _a_ basically
b[0].a = 312;
console.log(a[0].a)
That's because Arrays are non-primitives.
You need to imagine variable as wires to values. Every primitive type is imutable, so when you try to change the value of that variable, you change the "wire" that it points to, which is another unique value.
Every other non primitive value is mutable, so when you change the value of it, every other variable that is pointing to that value will now return that value changed.
If I do:
const fruit = { name: 'apple' } // {} creates a new value and points to it
const number = 1; // points to the primitive value 1
so if I do:
const anotherFruit = fruit;
anotherFruit.name = 'banana'; // changes the value of fruit
let anotherNumber = number;
number = 3; // value 1 is a primitive, so it can't be changed, will point to value 3
There's a small course by Dan Abramov that will make it easier for you to understand it: https://justjavascript.com

javascript: clicking numerical boxes - increment not working

using the code below, I've created a grid of buttons, 5x5, with random 1-25 numbers assigned to each button. They are to be clicked in numerical order, each's background turns red when clicked in the correct order. I can't use a global variable for this prompt. Without a global variable, I can't figure out how to increment the correctNumbers function which checks whether the right number is clicked each time. I think I'm missing something, a js function or something that would enable an incrementing variable declared within the incrementing function. I'm not looking for the whole explanation, just tips on functions i might not know about, and whether or not what i'm trying to do just isn't logicly possible.
<div id="numbers" class="hidden"></div>
<div id="youWon" class="hidden">You Won!</div>
The relevant JS:
... /**
* Gives the numbers a random order
* the "Fisher-Yates shuffle" found at: https://www.frankmitchell.org/2015/01/fisher-yates/
* #param {*} array
*/
const shuffle = (array) => {
let i = 0,
j = 0,
temp = null
for (i = array.length - 1; i > 0; i -= 1) {
j = Math.floor(Math.random() * (i + 1))
temp = array[i]
array[i] = array[j]
array[j] = temp
}
}
/**
* Generates an array of numbers 1-25
*/
const generateNums = () => {
document.getElementById("youWon").classList.toggle("hidden", "visible");
const numberArray = [];
for (let a = 1; a <= 25; a++) {
numberArray.push(a);
}
shuffle(numberArray);
let numEl = document.getElementById('numbers'); //write into html div id "numbers"
for (let b = 0; b <= 24; b++) { //loop to create button array
let newBtn = document.createElement('button'); //create buttons
newBtn.className = 'number'; //assign newBtns 'number' class
newBtn.innerText = numberArray[b]; //assign numbers to each button
numEl.appendChild(newBtn); //match with number elements in "numbers" array
newBtn.addEventListener("click", onNumberClick) //create function trigger
}
}
/**
* Creates a function to decide correct and incorrect clicks
* When a user clicks a number, if it is the next number in order, then it turns a different color for the remainder of the test
* If it is the wrong number, nothing happens
* #param {*} event
*/
const incrementNum = (correctNumber) => {
correctNumber++;
}
const onNumberClick = (event) => {
let correctNumber = 1; //start at 1
let numberVal = event.target; //apply it to clicks on the numbers
if (Number(numberVal.innerHTML) + 1 == incrementNum(correctNumber)) {
incrementNum(correctNumber);
numberVal.classList.add("red");
}
if (correctNumber == 26) {
document.getElementById("youWon").classList.toggle("visible"); //show win message if 25 is the last button and gets clicked
}
}
I would suggest that you count the number of elements in the DOM that have the class "red" and add 1... checking if the innerHTML is equal to that number to get the sequence right. So, instead of this:
if (Number(numberVal.innerHTML) + 1 == incrementNum(correctNumber)) {
incrementNum(correctNumber);
numberVal.classList.add("red");
}
You can have something like this:
if(Number(numberVal.innerHTML) == document.getElementsByClassName('red').length + 1) {
numberVal.classList.add("red");
}

How to get the next element on Map function?

I'm trying to make some coordinate plane functions on React native. But I'm having a problem that I don't know how to get the next element on my array.
This is my array:
[
{"M":["0","0"]},
{"H":"100"},
{"V":"0"},
{"H":"100"},
{"V":"100"},
{"H":"0"},
{"V":"100"},
{"H":"0"},
{"V":"0"},
]
This is my function:
const rotate = (pathArray, angle) =>{
if (angle > 0){
let vCordinate;
return pathArray.map((cordinate)=>{
if(Object.entries(cordinate)[0][0] == "M"){
let mCordinate = Object.entries(cordinate)[0][1];
mCordinate[0] = (parseInt(mCordinate[0]) * Math.cos(angle)) - (parseInt(mCordinate[1]) * Math.sin(angle));
mCordinate[1] = (parseInt(mCordinate[1]) * Math.cos(angle)) + (parseInt(mCordinate[0]) * Math.sin(angle));
return {[Object.entries(cordinate)[0][0]]: mCordinate};
}
//LOGIC TO GET NEXT ELEMENT
if(Object.entries(cordinate)[0][0] == "H"){
let hCordinate = Object.entries(cordinate)[0][1];
vCordinate = Object.entries(cordinate)[0][1]
return {[Object.entries(cordinate)[0][0]]: vCordinate};
}
if(Object.entries(cordinate)[0][0] == "V"){
return {[Object.entries(cordinate)[0][0]]: vCordinate};
}
})
}
return pathArray;
}
In this point I need to get the next element when I've hit "H".
How to do this?
The callback of map method accepts 3 arguments:
current item value;
current item index;
the array map was called upon.
So, you could use index to get next element value:
var newArray = myArray.map(function(value, index, elements) {
var next = elements[index+1];
// do something
});
or
var newArray = myArray.map(function(value, index) {
var next = myArray[index+1];
// do something
});
Note, the value of next variable may be undefined. Test the variable, if need, to prevent errors.

Javascript - How do I clear out a previous value in a DIV?

i'm making a game where 2 players are fighting one another.
I have it setup where the document writes the objects hp out (100). However, when I make a event where the player suffers 10 damage, it should write out 90 in the hp bar. Instead it writes out 10090.
How can I get it where the previous value gets updated, rather than it continuing to write beside the previous value?
function player (hp, mana, stamina){
this.hp = hp;
this.mana = mana;
this.stamina = stamina;
}
function npc (hp, mana, stamina) {
this.hp = hp;
this.mana = mana;
this.stamina = stamina;
}
var alistar = new player (100, 50, 30);
var dragon = new npc (100, 50, 30);
document.getElementById("hp").innerHTML += alistar.hp;
if ( 0 < 1) {
alistar.hp = alistar.hp - 10;
document.getElementById("hp").innerHTML += alistar.hp;
}
Doing the = sign works, but it removed any HTML words I had in there. I suppose I can make a 2nd div box for my HTML needs and keep the value seperate.
Just put = symbol instead of +=:
The = operator overwrite the previous value. On the other hand, the += is the union between the + operator and the = operator, and is the "shortway" to achieve the next:
For example, if you want to add a value to a variable you can do this:
var a = 3,
value = 10; /* Your value, i.e. 10 */
a = a + value; /* a values 13 */
BUT, you can get the same result using the += operators:
var a = 3,
value = 10; /* Your value, i.e. 10 */
a = += value; /* This adds the value of a to the value of value variable. */
As you can think, the value of a is 13, too as the below example.
Regarding to your code...
CODE:
if ( 0 < 1) {
alistar.hp = alistar.hp - 10;
document.getElementById("hp").innerHTML = alistar.hp; /* UPDATE */
}
if ( 0 < 1) {
alistar.hp = alistar.hp - 10;
document.getElementById("hp").innerHTML = alistar.hp;
}
+= is concatenating the values and adding them together (seemingly in string format). Instead, you want to use "=" to assign the value of the hp to the hp element, overwriting the existing innerHTML.

Categories

Resources