Change variable value inside forEach - javascript

I have three inputs and three variables, my goal is to change variables values with the values inside the inputs
const inputs = [
document.querySelector(".bill-input"),
document.querySelector(".custom"),
document.querySelector(".people-number"),
];
var bill = 0;
var tip = 0;
var people = 0;
i accomplished to do it this way
inputs[0].addEventListener("keyup", (e) => {
bill = Number(e.target.value);
});
inputs[1].addEventListener("keyup", (e) => {
tip = Number(e.target.value);
});
inputs[2].addEventListener("keyup", (e) => {
people = Number(e.target.value);
});
I'm pretty sure this is not the optimal way to do it, so i wanted to ask if there's a way to do it with forEach or any other method that does not require for me to write every single one each time.

Add a data attribute to each input.
Use an object to maintain the state of those inputs instead of n variables.
Have one handler that can update the object properties based on their id.
// Initialise the values object
const values = { bill: 0, tip: 0, people: 0 };
// Cache the inputs, and add listeners to them
const inputs = document.querySelectorAll('input');
inputs.forEach(input => input.addEventListener('keyup', handleChange));
// Grab the id from the input's dataset, and
// set the values object property to match
// the input value
function handleChange() {
const { id } = this.dataset;
values[id] = this.value;
console.log(JSON.stringify(values));
}
input { display: block; }
Bill<input data-id="bill">
Tip <input data-id="tip">
People <input data-id="people">
Additional documentation
Destructuring assignment

Yes, you can use forEach. I used a switch to get the index of the input element (in inputs const) to know what variable update.
Please see snippet below :
var bill = 0;
var tip = 0;
var people = 0;
const inputs = [
document.querySelector(".bill-input"),
document.querySelector(".custom"),
document.querySelector(".people-number"),
];
inputs.forEach(function(item,index){
item.addEventListener("keyup", (e) => {
const val = Number(e.target.value);
switch(index){
case 0 : bill = val; break;
case 1 : tip = val; break;
case 2 : people = val; break;
}
console.log(bill,tip,people)
});
});
<input value="3" type="number" class="bill-input">
<input value="10" type="number" class="custom">
<input value="100" type="number" class="people-number">

Related

Variable method not to repeat myself for: document.getElementById?

I'm looking for a method where I can make a variable containing the document.getElementById and include the correct value for the ID as a variable value. What I have now is this:
let lenght = parseInt(document.getElementById("lenght").value);
let start = parseInt(document.getElementById("start").value);
let end = parseInt(document.getElementById("end").value);
But what I would like to have is something like this:
let documentById = parseInt(document.getElementById($elementName).value)
let lenght = documentById("lenght");
let start = documentById("start");
let end = documentById("end");
Am I thinking in the correct way or is this a method that does not make sense? Any tips/suggestions are welcome as I try to learn.
You could accomplish this with a simple function that takes in the ID of the element as a parameter and returns the value as intended
function documentById(id) {
const el = document.getElementById(id);
if (!el) return undefined; // element doesn't exist
const value = parseInt(el.value, 10); // parsing string to a number (default radix is 10)
return isNaN(value) ? { number: false, value: value } : { number: true, value: value };
}
const { number, value } = documentById('end'); // if value isnt a number return false (to prevent errors);
if (number) console.log(value); // if value is a number log its value
else console.log('not a valid number')
Sure, you can make a function that returns just that.
const getValueById = (id) => parseInt(document.getElementById(id).value, 10);
const length = getValueById("length");
const start = getValueById("start");
const end = getValueById("end");
console.log({ length, start, end });
<input id="length" value="5" />
<input id="start" value="2" />
<input id="end" value="6" />

GTM - tracking latest input click value

My script
function() {
var inputs = document.getElementsByTagName("input"),
selectedRadios = [];
for (var i = 0;i < inputs.length;i++) {
if(inputs[i].type==="checkbox" && inputs[i].checked) {
selectedRadios.push(inputs[i].value);
}
}
return selectedRadios;
}
This script returns an array of all the checked buttons value. So, in my case, if I check three inputs the array will be for example: [167,168,169]
Issue: The array is auto sorted in ascending numerical order, while I want that the array is sorted based on which one was checked first, second, third,... .
To do that I edited the script above in this way
function() {
var inputs = document.getElementsByTagName("input"),
selectedRadios = [],
selectedRadios_latestchoice = [];
// get all checkboxs selected
for (var i = 0;i < inputs.length;i++) {
if(inputs[i].type==="checkbox" && inputs[i].checked) {
selectedRadios.push({filterValue : inputs[i].value, latestchoice : selectedRadios.length});
}
}
// sort value by last choice
selectedRadios.sort(function(a, b) {
return a.latestchoice - b.latestchoice;
}),
// parse data
var obj = JSON.parse(selectedRadios),
for (var s = 0;s < obj.length;s++) {
selectedRadios_latestchoice.push(obj[s].filterValue);
}
// return last value of the array "selectedRadios_latestchoice"
return selectedRadios_latestchoice[selectedRadios_latestchoice.length];
}
The logic is:
push the "input value" and the "array.length",
the "array.length" tell me if the input value was clicked first, second, third ..
sort the input value by the array.length value.
parse the json.
return the latest value of the array.
My attempt return an error. Any help?
There may be a more eligant way to do this, but I was able to use a forEach loop with a nested event listener running a function. In the function we run the event.target through a conditional that checks e.target.checked, if this returns true we push the value into an array, we then reduce that array creating an obj that saves the arr.length as property and the current value as value. Then we push that object into a final array to force the key from auto sorting.
const checkboxes = document.querySelectorAll('.check')
let val = []
const keyValPair = []
checkboxes.forEach((value) => {
value.addEventListener('change', getPositionAndValue)
})
function getPositionAndValue(e) {
if (e.target.checked) {
val.push(e.target.value)
var result = val.reduce(function(result, curr) {
result[val.length] = curr;
return result;
}, {})
keyValPair.push(result)
console.log(keyValPair)
}
}
<input class="check" value="167" type="checkbox">
<input class="check" value="168" type="checkbox">
<input class="check" value="169" type="checkbox">
<input class="check" value="170" type="checkbox">
<input class="check" value="171" type="checkbox">

How to get the value of an input type number and put it into a global variable JS

I want to get the value of an input type number and put it into a global variable. But in the console I get undefined. I need to use the value in other functions. How can I do that?
const bet = document.querySelector('#bet');
let Inputvalue;
bet.addEventListener('change', checkBet)
function checkBet(e) {
Inputvalue = e.target.value;
}
console.log(Inputvalue)
<input type="number" id="bet" value="" name="bet">
The checkBet() function will only be called after you change the value in the input. However, console.log() gets called right away, just as the JS parser reads the file. Since you've not assigned any value to the variable, you will get undefined.
You should either initialize the variable with a value (like 0), or move the console.log() inside the checkBet() function.
Option 1:
const bet = document.querySelector('#bet');
let Inputvalue;
bet.addEventListener('change', checkBet)
function checkBet(e) {
Inputvalue = e.target.value;
console.log(Inputvalue)
}
Option 2:
const bet = document.querySelector('#bet');
let Inputvalue = 0;
bet.addEventListener('change', checkBet)
function checkBet(e) {
Inputvalue = e.target.value;
}
console.log(Inputvalue)
Try this.
const bet = document.querySelector('#bet');
let Inputvalue;
bet.addEventListener('change', checkBet);
function checkBet(e) {
Inputvalue = e.target.value;
console.log(Inputvalue)
}
<input type="number" id="bet" name="bet"/>
Hope this helps

Using querySelector to get each letter a user inputs

Trying to make a web page that will get each letter a user inputs and output it in a phonetic alphabet. For example (user types: Hello)(Output: Hotel , Echo , Lima, Lima, Oscar). This is what I have so far just need some guidance on how to get the value of each letter and compare it to like an Array to get the output.
//define UI variables
const userInput = document.querySelector('#input');
const phoneticAlphabet = ["Alpha"," Bravo","Charlie"];
//load all event listeners
loadEventListeners();
function loadEventListeners() {
//add submit event
form.addEventListener('submit', submitInput);
}
//submit user input
function submitInput(e) {
console.log(userInput.value);
if (userInput.value === '') {
alert('Add Input');
}
e.preventDefault();
}
I presume that you would like to replace non-convertible characters from the input. For the same, I am using regular expression. I have also added the response in a "p" tag. And the code runs on clicking "Submit".
Update:
Extended my array for all alphabets :)
Update 2:
Thanks #CharlieBatista for pointing out. Now, the input accepts uppercase characters as well.
//define UI variables
const form = document.phoneticForm;
const userInput = document.querySelector('#input');
const output = document.querySelector('#output');
const phoneticAlphabet = ['Alpha','Bravo','Charlie','Delta','Echo','Foxtrot','Golf','Hotel','India','Juliet','Kilo','Lima','Mike','November','Oscar','Papa','Quebec','Romeo','Sierra','Tango','Uniform','Victor','Whiskey','X-ray','Yankee','Zulu'];
//load all event listeners
loadEventListeners();
function loadEventListeners() {
//add submit event
form.addEventListener('submit', submitInput);
}
//submit user input
function submitInput(e) {
e.preventDefault();
var value = userInput.value;
if (value === '') {
alert('Add Input');
} else {
value = value.replace(/[^a-zA-Z]/gi,'');
userInput.value = value;
value = value.toLowerCase();
var outputArr = [];
for(var i = 0; i < value.length; i++){
outputArr.push(phoneticAlphabet[value.charCodeAt(i)-97]);
}
output.innerHTML = outputArr.join(', ');
}
}
<form name="phoneticForm">
<input type="text" id="input">
<input type="submit">
</form>
<p id="output"></p>
You can use the key property on the keydown event of the field to get the character that was pressed.
Then check if the key is a printable key using key.length === 1 (see this answer).
If the key is printable, convert it to uppercase, then to its character code using String.prototype.charCodeAt() and then subtract 65 from it (character A). This will give you the index in your array.
If this index is within the bounds of the array, access the array and print the character.
const phoneticAlphabet = ['Alpha','Bravo','Charlie','Delta','Echo','Foxtrot','Golf','Hotel','India','Juliet','Kilo','Lima','Mike','November','Oscar','Papa','Quebec','Romeo','Sierra','Tango','Uniform','Victor','Whiskey','X-ray','Yankee','Zulu'];
document.querySelector('#input').addEventListener('keydown', e => {
const isPrintable = e.key.length === 1;
console.clear();
if (isPrintable) {
const idx = e.key.toUpperCase().charCodeAt(0) - 65;
if (idx >= 0 && idx < phoneticAlphabet.length) {
const phoneme = phoneticAlphabet[idx];
console.log(phoneme);
}
}
});
<input type="text" id="input">

Separate array of elements by attribute

Let's say I've got a form with several inputs, and I use a pretty standard jQuery statement to get them all:
var inputs = $("#some-form").find("input")
Now, I'd like to act on those inputs, but let's say I want to treat the radio button and/or checkbox groups as a single thing. How can I split inputs out into elements grouped by an attribute, say name. Note, that I don't know what the name is going to be when the processing starts.
In human terms, I need the logic do do something along the lines of:
Let me iterate over the list of inputs. For each input, let me check
to see if it's already been added to a placeholder array. If so,
leave it alone. If not, add it and everything with it's name to said
placeholder array (as a sub array).
Essentially, I'd like something like this:
[[<input type="text" name="name1">], [<input type="radio" name="name2">,<input type="radio" name="name2">]]
Try using attribute selector inside a filter.
var $formInput = $('#some-form').find('input');
var inputText = $formInput.filter('[type=text]')
var otherInput = $formInput.filter("[type=radio]")
.add($formInput.filter('[type=checkbox]'));
or even better
var otherInput = $formInput.filter(function () {
return this.type == 'radio' || this.type == 'checkbox';
});
DEMO: http://jsfiddle.net/utwaf/
How can I split inputs out into elements grouped by an attribute, say name
var elements = []; //elements by name
var $formInput = $('#some-form').find('input');
elements.push($formInput.filter(function() {
return this.name == 'name1';
});
elements.push($formInput.filter(function() {
return this.name == 'name2';
});
Note: All elements pushed into the array are jQuery objects.
function getInputsPartitioned(formEl) {
var inputEls = formEl.querySelectorAll("input");
var inputsByName = Object.create(null);
for (var i = 0; i < inputEls.length; ++i) {
var inputEl = inputEls[i];
var name = inputEl.name;
if (!(name in inputsByName)) {
inputsByName[name] = [];
}
inputsByName[name].push(inputEl);
}
// `inputsByName` now looks like this:
// {
// name1: [<input type="text" name="name1">],
// name2: [<input type="radio" name="name2">, <input type="radio" name="name2">]
// }
// To get it into arrays:
return Object.keys(inputsByName).map(function (name) {
return inputsByName[name];
});
}
Bonus: no jQuery needed.

Categories

Resources