Previously I made an onchange input, there are several inputs that have the same thing called by id. How do I call multiple
ids in one line of code? I tried to write it like this but failed:
function minmax() {
const inp_field = document.querySelectorAll("#input1, #input2, #input3, #input4");
let val = parseFloat(inp_field.value),
min = parseFloat(inp_field.min),
max = parseFloat(inp_field.max);
if (val < min) {
inp_field.value = min;
} else if (val > max) {
inp_field.value = max;
} else {
inp_field.value = val;
}
}
<input id="input1" type="text" onchange="minmax()" min="0.01" max="94.99">
<input id="input2" type="text" onchange="minmax()" min="0.1" max="99.99">
<input id="input3" type="text" onchange="minmax()" min="5" max="25">
<input id="input4" type="text" onchange="minmax()" min="1" max="10">
Assuming that you want to update each input value based on its min/max attributes as it changes:
There's no real need for those ids. If you wanted to group them you could use a class instead, but here I'm just picking up the inputs by element name.
Remove the requirement for inline JS and use addEventListener to attach listeners to each input.
You can use this (the context referring to the clicked element) in the function to make the code more concise.
You can remove this.value = val since the input value is already set.
Finally, while max/min aren't specified as attributes on a you can use with type="text" apparently you can still use them. But you may want to change to type="number".
const inputs = document.querySelectorAll('input');
inputs.forEach(input => {
input.addEventListener('change', minMax);
});
function minMax() {
const val = parseFloat(this.value);
const min = parseFloat(this.min);
const max = parseFloat(this.max);
if (val < min) this.value = min;
if (val > max) this.value = max;
}
<input type="text" min="0.01" max="94.99">
<input type="text" min="0.1" max="99.99">
<input type="text" min="5" max="25">
<input type="text" min="1" max="10">
I doubt you really need all that... try this and see if it serves your need.
function minmax(inp_field) {
let val = parseFloat(inp_field.value),
min = parseFloat(inp_field.min),
max = parseFloat(inp_field.max);
//below we call a function that checks if the value contains any scientific/engineering notation
val = decimalCount(val)
if (val < min) {
inp_field.value = inp_field.min;
} else if (val > max) {
inp_field.value = inp_field.max;
} else {
inp_field.value = val;
}
}
function decimalCount(val){
let valStr = val.toString(); //convert float to string
//check if the value include e-... example 1e-7
if(valStr.includes('e-')){
//get the value before the scietific notation
let beforeE = valStr.substr(0,valStr.indexOf('e'));
//the following removes a comma. example 0.000000017 == 1.7e-7
beforeE = beforeE.replace('.','')
//get the number of zeros after the scientific notation
let decimalPlace = valStr.substr((valStr.indexOf('-') + 1)) - 1
//we set a variable for the zeros after the .
let zeros = '.';
//assign the zeros to appear after the .
for(let i=0;i<decimalPlace;i++){
zeros += 0;
}
//concatenate the results and return the value for display
return 0 + zeros + beforeE;
}else{
//else, we return the min/max as it is
return val;
}
}
<input id="input1" type="text" onchange="minmax(this)" min="0.01" max="94.99">
<input id="input2" type="text" onchange="minmax(this)" min="0.00000001" max="99.99">
<input id="input3" type="text" onchange="minmax(this)" min="5" max="25">
<input id="input4" type="text" onchange="minmax(this)" min="1" max="10">
If your aim is to keep all the inputs in sync whenever one of them is changing, then a slight adjustment is required using forEach.
Keep in mind, however, that querySelectorAll produces a NodeList, not an Array:
function minmax() {
const inp_fields = document.querySelectorAll("#input1, #input2, #input3, #input4");
inp_fields.forEach(inp_field => {
let val = parseFloat(inp_field.value),
min = parseFloat(inp_field.min),
max = parseFloat(inp_field.max);
if (val < min) {
inp_field.value = min;
} else if (val > max) {
inp_field.value = max;
} else {
inp_field.value = val;
}
});
}
Just make sure to change your input fields type to number and set a proper default value (for example, 0), because otherwise your calculations will yield to NaN being set to all the other fields upon modifying any of them.
You can do this with a for loop.
function minmax() {
const inp_field_arr = ["input1", "input2", "input3", "input4"];
for (let i = 0; i < inp_field_arr.length; i++) {
inp_field = document.getElementById(inp_field_arr[i]);
let val = parseFloat(Number(inp_field.value)),
min = parseFloat(Number(inp_field.min)),
max = parseFloat(Number(inp_field.max));
if (val < min) {
inp_field.value = min;
} else if (val > max) {
inp_field.value = max;
} else {
inp_field.value = val;
}
}
}
<input id="input1" type="text" onchange="minmax()" min="0.01" max="94.99">
<input id="input2" type="text" onchange="minmax()" min="0.1" max="99.99">
<input id="input3" type="text" onchange="minmax()" min="5" max="25">
<input id="input4" type="text" onchange="minmax()" min="1" max="10">
A more efficient way of doing this, though, would be to get the value in the onChange part. This can also fix some errors that may occur.
You can do this by removing the let val, let min, and let max, and instead using onchange="minmax(parseFloat(this.value), parseFloat(this.min), parseFloat(this.max))", and making the function declaration function minmax(val, min, max).
More information about:
for loop MDN DigitalOcean DevDocs Wikipedia
Number MDN
like this ,ids are can change according your code ,like this, ids are can change according to your code,but logical is this
const elements=document.qeuerySelectorAll('#id, #id2,#id3');
elements.foreEach(funcion(element){
console.log(element);
});
Consider to use classes, instead of element ids, when you are dealing with multiple elements. And is, also, a best practice.
Then you can use a function like getElementsByClassName()
Related
I want to restrict the user input to two decimal places only at the same time restrict user input not greater than the maxvalue. My code below doesn't work together.
JS Code
var validate = function(e) {
var t = e.value;
e.value = (t.indexOf(".") >= 0) ? (t.substr(0, t.indexOf(".")) + t.substr(t.indexOf("."), 3)) : t;
}
var input = document.getElementById("amt");
// Add event listener
input.addEventListener("input", function(e){
var max = parseFloat(input.max);
this.setCustomValidity("");
console.log(this.value)
if(parseFloat(this.value) > max){
this.value = max;
} else if(this.validity.rangeUnderflow){
this.setCustomValidity("Does not reach the amount requirement");
}
});
html code
<input type="number" min="100" max="999.99" step=".01" name="amt" id="amt" oninput="validate(this)" required>
I want to show the user four input boxes, starting with 25% each of them. If the user changes any of the values in a input box the value displayed in the three others will calculate accordingly. Example :let's say that a user choose to change one of theme to 20% I expect the others to be 26.6
You can first get all the elements then add a class on focus remove it on blur. This class will be used to target rest of the element and update their value
//get all the input with specified name and add event lister to it
[...document.getElementsByName('userInp')].forEach(function(item) {
// on focusing adding a class to the current target
item.addEventListener("focus", function(e) {
e.target.classList.add('focus')
});
// removing the class on blurring from current target
item.addEventListener("blur", function(e) {
e.target.classList.remove('focus')
});
item.addEventListener('keyup', function(e) {
// get the value from the target input
let getVal = e.target.value;
if (getVal < 100) {
// devide equally among rest of the inputs for this example it is 3
let eachVal = (100 - getVal) / 3
// then select all the input which does not have class focus
// and update their value
document.querySelectorAll("input:not(.focus)").forEach(function(elem) {
elem.value = eachVal.toFixed(2)
})
}
})
})
<input type='text' name='userInp' value='25'>
<input type='text' name='userInp' value='25'>
<input type='text' name='userInp' value='25'>
<input type='text' name='userInp' value='25'>
While brk's answer shows a way to manage setting all other fields to an equally shared value, it is probably no what most people want. The following will change the other fields according to their relative ratio to each other.
Note: Special case if one item is 100%
Please note that the following solution does not handle the special case where one item takes it all (100%) and all other items are 0% and then the 100% item is reduced by any amount. In this case the new remaining value (100% - new value) could be split equally among the other items. But because this might be use case dependent, I leave this as an easy exercise to integrate.
Text fields
var isRunning = false;
//get all the input with specified name and add event lister to it
[...document.getElementsByName('userInp')].forEach(function(item) {
if (!isRunning) {
item.addEventListener('change', function(element) {
// get the value from the target input
const getVal = parseFloat(element.target.value);
if (getVal <= 100) {
isRunning = true;
// devide among rest while keeping their relative ratio
const otherFields = Array.from(document.getElementsByName("userInp")).filter(e => e != item);
const change = 100 - otherFields.map(e => parseFloat(e.value)).reduce((prev, curr) => prev + curr) - getVal;
const oldRest = 100 - (getVal + change);
otherFields.forEach(function(elem) {
const old = parseFloat(elem.value);
elem.value = Math.floor((old + ((old / oldRest) * change)) * 100) / 100;
})
isRunning = false;
}
})
}
})
<input type='number' name='userInp' value='25'>
<input type='number' name='userInp' value='25'>
<input type='number' name='userInp' value='25'>
<input type='number' name='userInp' value='25'>
Sliders
Here is the same with sliders for better visualization:
var isRunning = false;
//get all the input with specified name and add event lister to it
[...document.getElementsByName('userInp')].forEach(function(item) {
if (!isRunning) {
item.addEventListener('change', function(element) {
// get the value from the target input
const getVal = parseFloat(element.target.value);
if (getVal <= 100) {
isRunning = true;
// devide among rest while keeping their relative ratio
const otherFields = Array.from(document.getElementsByName("userInp")).filter(e => e != item);
const change = 100 - otherFields.map(e => parseFloat(e.value)).reduce((prev, curr) => prev + curr) - getVal;
const oldRest = 100 - (getVal + change);
otherFields.forEach(function(elem) {
const old = parseFloat(elem.value);
elem.value = Math.floor((old + ((old / oldRest) * change)) * 100) / 100;
})
isRunning = false;
}
})
}
})
<input type='range' name='userInp' value='25' min="0", max="100">
<input type='range' name='userInp' value='25' min="0", max="100">
<input type='range' name='userInp' value='25' min="0", max="100">
<input type='range' name='userInp' value='25' min="0", max="100">
function pretest() {
var a = document.getElementById('pre').value;
var result = parseInt(a);
if (a <= 50) {
document.getElementById('val').value = 1;
}else if(50<a && a<= 80){
document.getElementById('val').value = 2;
}else{
document.getElementById('val').value = 3;
}
}
function posttest(){
var a = document.getElementById('post').value;
var result = parseInt(a);
if (a <= 50) {
document.getElementById('val1').value = 1;
}else if(50<a && a<= 80){
document.getElementById('val1').value = 2;
}else{
document.getElementById('val1').value = 3;
}
}
function all(){
var a = document.getElementById('val').value;
var b = document.getElementById('val1').value;
var c = parseInt(a) + parseInt(b);
if (!isNaN(c)) {
document.getElementById('total').value = c;
}
}
<input onkeyup="pretest();" type="text" id="pre" name="pretest">
<input onkeyup="all();" type="text" id="val" name="val" disabled="disabled">
<input onkeyup="posttest();" type="text" id="post" name="posttest">
<input onkeyup="all();" type="text" id="val1" name="val1" disabled="disabled">
<input onkeyup="total();" type="text" id="total" name="total" disabled="disabled">
i have 5 text field
A1 A2(value onkeyup from A1 and disabled is true)
B1 B2(value onkeyup from B1 and disabled is true)
C(A2+B2 and disabled textfield)
How to get value for C textfield ? i used onkeyup, but didn't work
There are several things amiss in your code.
never, ever use parseInt(foo) without the radix-argument, especially when foo is arbitrary input. parseInt will otherwise take input 012 and think it's an octal value you gave it. Thus, make that parseInt(a, 10) to get a decimal, or use Number(a)
onkeyup won't fire on a disabled element - how could it? Nobody will be able to press a key there, since it's disabled. What you probably want is onchange, however...
...onchange (or oninput, which is a little more trigger-happy and what I've used below) won't fire when you manually set an element's value; it doesn't in vanilla JS, nor when using jQuery's val() - you have to trigger it manually
your code example is rushed, incomplete and I had to work considerably longer and harder to understand what you want than should be necessary; regardless...
/*
Especially with function names like `all` and `total`, you will want
to make sure to set up some sort of namespacing, e.g. using the
Revealing Module Pattern or other. These functions are attached to
the global window object and can be overriden by anything and anybody,
causing at least hard-to-trace bugs, maybe worse
*/
function pretest() {
var a = document.getElementById('pre').value;
var result = parseInt(a, 10);
if (a <= 50) {
document.getElementById('val').value = 1;
} else if (50 < a && a <= 80) {
document.getElementById('val').value = 2;
} else {
document.getElementById('val').value = 3;
}
// you have to explicitly call all() here, as the input-event
// won't be fired when manually setting value
all();
}
function posttest() {
var a = document.getElementById('post').value;
var result = parseInt(a, 10);
if (a <= 50) {
document.getElementById('val1').value = 1;
} else if (50 < a && a <= 80) {
document.getElementById('val1').value = 2;
} else {
document.getElementById('val1').value = 3;
}
all()
}
function all() {
var a = document.getElementById('val').value;
var b = document.getElementById('val1').value;
var c = parseInt(a, 10) + parseInt(b, 10);
if (!isNaN(c)) {
document.getElementById('total').value = c;
}
total();
}
total = function() {
//TODO implement
}
document.getElementById('pre').addEventListener('input', window.pretest);
document.getElementById('post').addEventListener('input', window.posttest);
<label for="pre">PRE</label><br>
<input type="text" id="pre" name="pretest">
<br><br>
<label for="val">val</label><br>
<input type="text" id="val" name="val" disabled="disabled">
<br><br>
<label for="post">POST</label><br>
<input type="text" id="post" name="posttest">
<br><br>
<label for="val1">val1</label><br>
<input type="text" id="val1" name="val1" disabled="disabled">
<br><br>
<label for="total">TOTAL</label><br>
<input type="text" id="total" name="total" disabled="disabled">
You can get value as from normal text input
function myFunction(){
document.getElementById("textPlace").disabled = true;
console.log(document.getElementById("textPlace").value)
}
<input type="text" onkeyup="myFunction()" id="textPlace">
I'm working on an Angular 4 project. I have an HTML <input type="number"> with min max and step attributes. My goal is to prevent typing numbers beyond the min-max range that is user friendly. How can I do that?
function myFunction(e) {
var min = -100;
var max = 100;
var txtValue = document.getElementById("txt").value;
var pressedValue = e.key;
var combined = parseFloat(txtValue, pressedValue);
console.log(`OLD:${txtValue}\nNEW:${pressedValue}\nCOMBINED:${combined}`);
if (combined > max) {
e.preventDefault();
console.log('ohhw snapp');
}
}
<input type="number" id="txt" value="Hello" onkeydown="myFunction(event)" min="-100" max="100" step="0.05">
My JSFiddle example
For UX reasons, I'd recommend something more like this. It may confuse the user if they just think their keyboard is not working.
$('.range-enforced').on('change', function(e){
var min=parseFloat($(this).attr('min'));
var max=parseFloat($(this).attr('max'));
var curr=parseFloat($(this).val());
if (curr > max) { $(this).val(max); var changed=true; }
if (curr < min) { $(this).val(min); var changed=true; }
if (changed) {
$warning = $(this).siblings('.warning')
$warning.text('Only ' + min + ' through ' + max + ' allowed');
$warning.show()
$warning.fadeOut(2500);
}
});
input + .warning {
background: #ffff99;
display: inline-block
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="range-enforced" min="-100" max="100" />
<div class="warning" style="display: none;"></div>
The first problem I see is you are providing 2 parameters to parseFloat which only accepts 1 (maybe you got confused with parseInt which takes 2 parameters- a string and a radix. You should combine the numbers first and do 1 parse float on the combined value.
for example
function myFunction() {
var min = -100;
var max = 100;
var inputRef = document.getElementById("txt");
var txtValue = inputRef.value;
if(isNaN(parseFloat(txtValue))){
console.log("warning input is not a number");
return;
}
var newNum = parseFloat(txtValue);
console.log(`NEW:${newNum}`);
if (newNum > max || newNum < min) {
console.log('input not in range (' + min + ", " + max + ")");
inputRef.value = "";
}
}
<input type="number" id="txt"
onkeyup="myFunction()"
min="-100"
max="100"
step="0.05"
>
The input will reset back to empty now if the input is not in range on keyup. As per the comment above you can use this to notify the user of the problem.
I have a dynamic set of input fields being generated. They all get named sequentially and each has an onFocus() handler. Just before each Input element is a div with a corresponding Id where I grab a dollar value from.
<input type="hidden" name="balance" value="2500.0" />
<div id="invoiceAmount0">$500.00</div>
<input type="text" size="8" id="invoiceBalance0" name="invoiceBalance0" value="" onfocus="setBalance(this)" />
<div id="invoiceAmount1">$500.00</div>
<input type="text" size="8" id="invoiceBalance1" name="invoiceBalance1" value="" onfocus="setBalance(this)" />
<div id="invoiceAmount2">$500.00</div>
<input type="text" size="8" id="invoiceBalance2" name="invoiceBalance2" value="" onfocus="setBalance(this)" />
The JS onFocus handler is as follows:
function setBalance(e) //e should be an input field element
{
var balance = document.PaymentForm.balance.value;
var remainder = balance;
var index = 0;
var paymentField = document.getElementById('invoiceBalance'+index); //get the first input payment element
while (paymentField != null && paymentField != e) //start with the first field and calculate the remaining balance
{
var paymentApplied = paymentField.value.replace(/[^0-9\.]+/g,"");
remainder = remainder - paymentApplied;
index++;
paymentField = document.getElementById('invoiceBalance'+index);
}
while (e == paymentField) //set the selected elements value
{
var invoiceBalance = document.getElementById('in'+index).innerHTML.replace(/[^0-9\.]+/g,"");
if (parseFloat(remainder) > parseFloat(invoiceBalance))
e.value = parseFloat(invoiceBalance).toFixed(2).toLocaleString();
else
e.value = parseFloat(remainder).toFixed(2).toLocaleString();
index++;
paymentField = document.getElementById('invoiceBalance'+index);
}
while (paymentField != null) //blank out the rest of the input fields
{
paymentField.value = '';
index++;
paymentField = document.getElementById('invoiceBalance'+index);
}
e.select();
}
The concept here is to calculate the remaining balance and set the input field's value as the user focuses the fields.
The problem is that The "this" parameter is always set to the first Input element "invoiceBalance0". I'm expecting it to be set to the element referring to it in it's onFocus handler.
What am I not seeing?
I'm unable to duplicate the error you describe, but I did notice what appears to be a typo:
var invoiceBalance = document.getElementById('in'+index).innerHTML.replace(/[^0-9\.]+/g,"");
looks like it should be
var invoiceBalance = document.getElementById('invoiceAmount'+index).innerHTML.replace(/[^0-9\.]+/g,"");
function setBalance(e) //e should be an input field element
{
var balance = document.querySelector('[name="balance"]').value;
var remainder = balance;
var index = 0;
var paymentField = document.getElementById('invoiceBalance' + index); //get the first input payment element
while (paymentField != null && paymentField != e) //start with the first field and calculate the remaining balance
{
var paymentApplied = paymentField.value.replace(/[^0-9\.]+/g, "");
remainder = remainder - paymentApplied;
index++;
paymentField = document.getElementById('invoiceBalance' + index);
}
while (e == paymentField) //set the selected elements value
{
var invoiceBalance = document.getElementById('invoiceAmount' + index).innerHTML.replace(/[^0-9\.]+/g, "");
if (parseFloat(remainder) > parseFloat(invoiceBalance))
e.value = parseFloat(invoiceBalance).toFixed(2).toLocaleString();
else
e.value = parseFloat(remainder).toFixed(2).toLocaleString();
index++;
paymentField = document.getElementById('invoiceBalance' + index);
}
while (paymentField != null) //blank out the rest of the input fields
{
paymentField.value = '';
index++;
paymentField = document.getElementById('invoiceBalance' + index);
}
e.select();
}
<input type="hidden" name="balance" value="2500.0" />
<div id="invoiceAmount0">$500.00</div>
<input type="text" size="8" id="invoiceBalance0" name="invoiceBalance0" value="" onfocus="setBalance(this)" />
<div id="invoiceAmount1">$500.00</div>
<input type="text" size="8" id="invoiceBalance1" name="invoiceBalance1" value="" onfocus="setBalance(this)" />
<div id="invoiceAmount2">$500.00</div>
<input type="text" size="8" id="invoiceBalance2" name="invoiceBalance2" value="" onfocus="setBalance(this)" />
It's work after changing this line :
var invoiceBalance = document.getElementById('in'+index).innerHTML.replace(/[^0-9\.]+/g,"")
To :
var invoiceBalance = document.getElementById('invoiceBalance'+index).innerHTML.replace(/[^
0-9\.]+/g,"");
that because you don't have an id like in[index] but this form invoiceBalance[index], hope that will help See
Working Fiddle.