Don't allow typing numbers between max and min value - javascript

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.

Related

How to call getElementById() on multiple ids

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()

Prevent inserting value greater than max at the same time restrict to decimal

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>

While Loop Input Issue

I am trying to make a program that takes numbers from the user until they input a 0, the output how many positive and negative numbers were input, while also telling the user whether the number they input was positive, negative, or zero, however, when I use it, it crashes the webpage immediately if anything but a 0 is input. So I was wondering where this issue would be coming from and how I could resolve it.
JS:
var pos = 0;
var neg = 0;
var inp = 1;
function interpreter() {
while (inp != 0) {
inp = (document.getElementById("number"));
if (inp < 0) {
document.getElementById("output1").innerHTML = "Input is: negative";
neg += 1;
} else if (inp > 0) {
document.getElementById("output1").innerHTML = "Input is: positive";
pos += 1;
} else {
document.getElementById("output1").innerHTML = "Input is: zero";
document.getElementById("output2").innerHTML = pos + " positive numbers were inputted";
document.getElementById("output3").innerHTML = neg + " negative numbers were inputted";
}
}
}
Where "number" is a text field for input, and the function is called upon the press of a button. Thanks in advance!
You're misunderstanding the event-processing nature of JavaScript.
If you have a while loop like that, you'll never yield control back to the browser itself, to handle user input, etc. You may be looking for something like this -- in addition to the removal of the explicit loop, note how the handling of inp has changed; previously you were comparing strings to numbers.
var pos = 0;
var neg = 0;
function interpret() {
var inp = parseInt(document.getElementById("number").value);
if (inp < 0) {
document.getElementById("output1").innerHTML = "Input is: negative";
neg += 1;
} else if (inp > 0) {
document.getElementById("output1").innerHTML = "Input is: positive";
pos += 1;
} else {
document.getElementById("output1").innerHTML = "Input is: zero";
document.getElementById("output2").innerHTML =
pos + " positive numbers were inputted";
document.getElementById("output3").innerHTML =
neg + " negative numbers were inputted";
}
}
<form onsubmit="interpret();event.preventDefault()">
<input id="number">
<input type="submit" value="Interpret value">
</form>
<div id="output1"></div>
<div id="output2"></div>
<div id="output3"></div>
If you really want my suggest:
var pos = 0
, neg = 0
;
document.forms['my-form'].addEventListener('submit',function(evt)
{
evt.preventDefault()
let inp = this.number.valueAsNumber
{
if (inp < 0)
{
this.out_1.textContent = 'Input is: negative'
neg++
}
else if (inp > 0)
{
this.out_1.textContent = 'Input is: positive'
pos++
}
else
{
this.out_1.textContent = 'Input is: zero';
this.out_2.textContent = pos + ' positive numbers were inputted'
this.out_3.textContent = neg + ' negative numbers were inputted'
}
}
})
label, button, output { display: block; margin:.4em; }
<form name="my-form">
<label>
Input:
<input name="number" type="number" min="-32768" max="32768" value="1">
</label>
<button type="submit"> enter </button>
<output name="out_1"></output>
<output name="out_2"></output>
<output name="out_3"></output>
</form>

A character counter in js?

So I am currently programming my very first website. I am using pure javascript. A part of it will be a comments section - which are stored in a SQL- Database on the server. I want comments to have a maximum length. After searching the web I found this solution. Please do note that this solution is far from perfect.
var maxchar = 160;
var i = document.getElementById("textinput");
var c = document.getElementById("count");
c.innerHTML = maxchar;
i.addEventListener("keydown", count);
function count(e) {
var len = i.value.length;
if (len >= maxchar) {
e.preventDefault();
} else {
c.innerHTML = maxchar - len - 1;
}
}
textarea {
display: block;
width: 200px;
height: 100px;
}
Remaining characters: <span id="count"></span>
<textarea id="textinput">
</textarea>
I found a lot of similar solutions also using jQuery. Now this solution has two major flaws. First it counts the characters before the new character is entered since the registered event is the keydown event - value.length will always give the old count. Secondly once you hit the maximum amount of characters it will prevent all user input - there is no way to delete characters anymore.
Registering the count to keyup doesn't help either - it can't prevent the input of the keydown event.
What is a better solution than this?
So after playing around with it for a bit I came up with this solution. The trick is to split up the count function into two parts - one which counts the characters and one which prevents the user input. Register the preventInput() on keydown, such that the input is prevented before entering, and register the count() on keyup, such that the new value of length is used in the function.
function preventInput(event) {
if (event.target.id == 'commentText')
var maxchar = 255;
else
var maxchar = 20;
//I'm using target here, such that I can use this as a callback for different textfields
var len = event.target.value.length;
var key = event.keyCode || event.which;
//prevent every input apart from UP, DOWN, LEFT, RIGHT and BACKSPACE
if (len >= maxchar && (key != 8 && !(key >= 37 && key <= 40)))
event.preventDefault();
}
function count(event) {
//different lengths for different textfields
if (event.target.id == 'commentText')
var maxchar = 255;
else
var maxchar = 20;
var len = event.target.value.length;
//setting the remaining chars field depending whether Author or Text triggered the event
document.getElementById("remain" + event.target.id.split('comment')[1]).innerHTML = 'Remaining characters:' + (maxchar - len);
//disable the submit button when the user entered too many chars (CTRL + V)
var btn = document.getElementById("submitBtn");
if (len > maxchar)
btn.disabled = true;
else
btn.disabled = false;
}
function setup() {
//setting to events
document.getElementById("commentAuthor").addEventListener("keydown", preventInput);
document.getElementById("commentAuthor").addEventListener("keyup", count);
document.getElementById("commentText").addEventListener("keydown", preventInput);
document.getElementById("commentText").addEventListener("keyup", count);
//initial count
document.getElementById("remainAuthor").innerHTML += 20;
document.getElementById("remainText").innerHTML += 255;
}
.charCounter {
opacity: 0.4;
}
<body onload="setup()">
<form>
<fieldset style="display: inline-block;">
<legend>Submit a comment</legend>
Name:
<input type="text" id="commentAuthor" name="Name:">
<div class="charCounter" id="remainAuthor">Remaining characters:</div>
<textarea name="comment" id="commentText" rows="4" cols="100"></textarea>
<div class="charCounter" id="remainText">Remaining characters:</div>
<br>
<input type="submit" id="submitBtn" value="Submit Comment!">
</fieldset>
</form>
</body>
You can modify the first snipped into something like this
var maxchar = 160;
var i = document.getElementById("commentText");
var c = document.getElementById("remainText");
c.innerHTML = maxchar;
i.addEventListener("keydown", count);
function count(e) {
var len = i.value.length;
len >= maxchar ? i.value = i.value.slice(0,len-1) : c.innerHTML = maxchar - len - 1;
}
<body onload="setup()">
<form>
<fieldset style="display: inline-block;">
<legend>Submit a comment</legend>
Name:
<input type="text" id="commentAuthor" name="Name:">
<div class="charCounter" id="remainAuthor">Remaining characters:</div>
<textarea name="comment" id="commentText" rows="4" cols="100"></textarea>
<div class="charCounter" id="remainText">Remaining characters:</div>
<br>
<input type="submit" id="submitBtn" value="Submit Comment!">
</fieldset>
</form>
</body>

Javascript total return NaN for 4 digits num

Here is the javascript for calculating the price of the item the problem is that
whenever the price is 4 digits the value that return is NaN.
here's my hidden field for the price:
<input type="hidden" name="price" id="price"class="price" value="4500"readonly >
here's for my quantity field
<input type="number" name="quant" id="quant" value="2" />
here's for my shipment fee
<select id="shipment" onchange="myFunction3()" name="shipment2" disabled>
<option value="100" data-quantity="1">1 for 100 pesos </option>
</select
here's for the total price
<input type="text" id="demo" name="total_price" style="margin-top:10px;margin-left:5px;" readonly>
Script for changing the value of shipment
<script type="text/javascript">
document.getElementById('quant').addEventListener("keyup", function(){
var value = parseInt(this.value, 20),
selectEle = document.getElementsByTagName('select')[0],
options = selectEle.options,
selectedNum = 0;
for(var i = 0; i < options.length; i++) {
//checking the exact string with spaces (" " + value + " ")
if(options[i].textContent.indexOf(" " + value + " ") > -1) {
selectedNum = i;
}
}
selectEle.selectedIndex = selectedNum ? selectedNum : 0;
}, false);
</script>
Calculating all the values
function myFunction3() {
var y= document.getElementById("shipment").value;
return y;
}
<script>
$("#price,#quant,#shipment").keyup(function () {
if(+myFunction3() =="" )
{
$('#demo').val(0);
}
else if($('#trigger')=="checked") //this is the problem
{
$('#demo').val($('#price').val() * $('#quant').val() ;
}
else
{
$('#demo').val($('#price').val() * $('#quant').val() + +myFunction3());
}
});
</script>
Not sure if this was just typed incorrectly in here, but you have a syntax error (missing closing parenthesis) near the problem area:
$('#demo').val($('#price').val() * $('#quant').val() ;
Should be:
$('#demo').val($('#price').val() * $('#quant').val());
I think it would be much better to ensure you aren't working with strings before you do math on them:
var price = parseInt($('#price').val(), 10);
var quantity = parseInt($('#quant').val(), 10);
$('#demo').val(price * quantity);
You could go further and ensure that neither of them are NaN prior to working with them:
var price = parseInt($('#price').val(), 10);
var quantity = parseInt($('#quant').val(), 10);
if(!isNaN(price) && !isNaN(quantity)) {
$('#demo').val(price * quantity);
} else {
alert('Please enter numbers only!');
}

Categories

Resources