I am trying to run a calculation that populates a text box based on an onblur event. For some reason, my result is showing a NaN. I am not used to JS so any help will be appreciated.
NOTE: I am most actively working on the last function - markupNumCheck() because once this function is working I can simply just apply it to the other two functions.
Here is the JS:
function unitToSales(){
var unitPrice = document.getElementById("inputCost");
var percentMarkup = document.getElementById("inputMarkup");
var salesPrice = document.getElementById("inputPrice");
parseInt(unitPrice.value);
parseInt(percentMarkup.value);
parseInt(salesPrice.value);
if(unitPrice.value != "" && percentMarkup.value != "" ){
salesPrice.value = (unitPrice * (1+percentMarkup));
}
}
function salesToUnit(){
var unitPrice = document.getElementById("inputCost");
var percentMarkup = document.getElementById("inputMarkup");
var salesPrice = document.getElementById("inputPrice");
parseInt(unitPrice.value);
parseInt(percentMarkup.value);
parseInt(salesPrice.value);
if(percentMarkup.value != "" && salesPrice.value != "" ){
unitPrice.value = parseInt(unitPrice * (1+percentMarkup));
}
}
function markupNumCheck(){
var unitPrice = document.getElementById("inputCost");
var percentMarkup = document.getElementById("inputMarkup");
var salesPrice = document.getElementById("inputPrice");
parseInt(unitPrice.value);
parseInt(percentMarkup.value);
parseInt(salesPrice.value);
if(unitPrice.value != "" && percentMarkup.value != "" ){
salesPrice.value = (unitPrice * (1+percentMarkup));
} else if (percentMarkup.value != "" && salesPrice.value != "" ){
unitPrice.value = (unitPrice * (1+percentMarkup));
}
}
And here is HTML where I call code:
NOTE: This obviously is a form, I did not copy the entire document because the rest is irrelevant.
<div class="form-row">
<div class="form-group col-md-3">
<div class="form-group">
<label for="inputCost">Unit Cost</label>
<input type="text" class="form-control" id="inputCost" name="inputCost" onblur="unitToSales()" value="">
</div>
</div>
<div class="form-group col-md-3">
<div class="form-group">
<label for="inputMarkup">Percent Markup</label>
<input type="text" class="form-control" id="inputMarkup" name="inputMarkup" onblur="markupNumCheck()">
</div>
</div>
<div class="form-group col-md-3">
<div class="form-group">
<label for="inputCost">Sales Price</label>
<input type="text" class="form-control" id="inputPrice" name="inputPrice" onblur="salesToUnit()">
</div>
</div>
<div class="form-group col-md-3">
<div class="form-group">
<label for="inputQuantity">Quantity</label>
<input type="text" class="form-control" id="inputQuantity" >
</div>
</div>
</div>
Thank you all again for any help that you may be able to give.
parseInt will return the parsed integer value. When you call parseInt(value) and don't assign the value to a variable, the parsed value is just discarded. You are using the variable unitPrice after as a number, but it actually holds a DOM element, that is why you get the NaN.
You can fix it by inlining the parseInt call in your expression:
salesPrice.value = (parseInt(unitPrice.value) * (1+parseInt(percentMarkup)));
You need to assign each of your variables to the parseInt result.
So for example you'd reuse the unitPrice variable and assign it to the parseInt result
var unitPrice = document.getElementById("inputCost");
unitPrice = parseInt(unitPrice);
I noticed that every time you tried to use parseInt that you don't save the result like so:
var resultInt = parseInt(SomeString);
So when you try to calculate your values together you get NaN because they still in string form.
If you look at this if-statement for example in salesToUnit():
if(percentMarkup.value != "" && salesPrice.value != "" ){
unitPrice.value = parseInt(unitPrice * (1+percentMarkup));
}
unitPrice and percentMarkup are not parsed as integers so you are adding 1 (an integer) to percentMarkup (a string) and then multiplying it to unitPrice(also a string) and THEN parsing the result giving you NaN and setting that to unitPrice.value.
I would like to add that the parseInt calls that happen in the beginning of salesToUnit() when would seem unnecessary since if theres no value in percentMarkup and SalesPrice and would be better let till once you do you check. I would flip it around like this and change salesToUnit() to something like this:
if(percentMarkup.value != "" && salesPrice.value != "" )
{
var salesPriceInt = parseInt(salesPrice.value);
var percentMarkupInt = parseInt(percentMarkup.value);
unitPrice.value = unitPriceInt * (1+percentMarkupInt);
}
Also incorporating the safeParseInt function mentioned by #Vitalii would help as well to be even safer!
I hope you find this useful!
Related
Despite not being linked (to my knowledge), when inputting the Celsius number, the Fahrenheit formula will run and be implemented to the Celsius output, with the correct formula being outputted on the Fahrenheit output, and vice versa when inputting a Fahrenheit number.
Image
I have tried several if statements but they only seem to work for one of the outputs with the other having no value result at all.
**HTML//Bootstrap**
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">C°</span>
<input type="number" class="form-control" id="cAmount" placeholder="Celsius">
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">F°</span>
<input type="number" class="form-control" id="fAmount" placeholder="Fahrenheit">
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">Celsius Temperature</span>
<input type="number" class="form-control" id="celsius-result" disabled>
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">Fahrenheit Temperature</span>
<input type="number" class="form-control" id="f-res" disabled>
</div>
</div>
**Javascript**
let formSubmit = document.querySelector('#tempCalculator')
formSubmit.addEventListener('submit', runEvent);
function runEvent(e) {
let celInput = document.querySelector('#cAmount');
let fahInput = document.querySelector('#fAmount');
let celResult = document.querySelector('#celsius-result')
let fahResult = document.querySelector('#f-res');
//input
let fahVal = parseFloat((celInput.value * 9/5) + 32);
let celVal = parseFloat((fahInput.value - 32) * 5/9);
//output
celResult.value = celVal.toFixed(2);
fahResult.value = fahVal.toFixed(2);
//stop form refreshing
e.preventDefault();
}
Expected would be just to have one correct value appear in the corresponding output, this does happen, but an incorrect value appears in the unexpected output.
Here's a Codepen link for the full application: https://codepen.io/str-99/pen/NmwXJz
If I'm understanding you correctly this is one way to accomplish what you're trying:
let formSubmit = document.getElementById('tempCalculator');
formSubmit.addEventListener('submit', runEvent);
function runEvent(e) {
let celInput = document.querySelector('#cAmount');
let fahInput = document.querySelector('#fAmount');
let celResult = document.querySelector('#celsius-result')
let fahResult = document.querySelector('#f-res');
//input
let fahVal = parseFloat((celInput.value * 9/5) + 32);
let celVal = parseFloat((fahInput.value - 32) * 5/9);
//output
celResult.value = Number(fahInput.value) > 0 ? celVal.toFixed(2) : '';
fahResult.value = Number(celInput.value) > 0 ? fahVal.toFixed(2) : '';
//reset input boxes
document.getElementById('cAmount').value = '';
document.getElementById('fAmount').value = '';
e.preventDefault();
}
The ternary operator works great for instances like this. We can simply change the value to an empty string when it's not the right/desired input. And for added measure clearing out the input boxes to 'reset' after each calculation.
I need help with a piece of JavaScript. I have this code:
<script>
function FilterInput(event) {
var keyCode = ('which' in event) ? event.which : event.keyCode;
isNotWanted = (keyCode == 69);
return !isNotWanted;
};
function handlePaste(e) {
var clipboardData, pastedData;
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text').toUpperCase();
if (pastedData.indexOf('E') > -1) {
e.stopPropagation();
e.preventDefault();
}
};
</script>
I would like to limit the user's input to only 5 digits. For example, for this entry box, I'd like no more than five numbers to be allowed (12345 for example) and no periods:
<div class="col-md-3">
<div class="form-group">
<label>Customer Number</label>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-hashtag"></i></span>
<input name="CustomerNumber" type="number" class="form-control" onkeydown="return FilterInput(event)" onpaste="handlePaste(event)" required>
</div>
</div>
<!-- /.form-group -->
</div>
<!-- /.col -->
How would I achieve this? I know for
type="text"
it allows limiting spaces by using "maxlength."
One way to do this is to trap the input, check if it passes your validation checks, and if so, proceed, if not, set it to the last known good value, like so:
var oldValue = "";
// listen for "input" event, since that handles all keypresses as well as cut/paste
document.getElementById("myInput").addEventListener('input', function (event) {
var input = event.target;
if (validateInput(input.value)) {
// update old value with new value
oldValue = input.value;
}
else {
// set value to last known valid value
input.value = oldValue;
}
});
function validateInput(str) {
// check length, if is a number, if is whole number, if no periods
return /^[0-9]{0,5}$/.test(str);
}
Test: <input type="text" id="myInput"/><br/>
Try typing/pasting invalid input
all the answers given here previously before mine are all outdated previous
I think solving this question is best answered by
Javascript slice is used to maintain character length
Javascript replace to maintain only numbers are taken
javascript oninput event to prevent the user does not use copy and paste to inject / input invalid character javascript.
<script>
function validate(field) {
let val = field.value;
let data = val.replace(/[^0-9]/g, "");
field.value = data.slice(0,16);
}
</script>
<label for="atmno">Payment card Number</label>
<input name="atmno" type="text" oninput="validate(this)">
I briefly described the answer on an article I wrote here: https://shopinson.com/javascript/javascript-validates-payment-card-number/
Well you could instead of choosing a number type input, use a text type input, where the maxlength attribute works and throw an error with JavaScript if the value is not a number. Like,
if(isNaN(input.value)){ // error code here }
A pure js and dom manipulation solution
Adding an Id attribute for simplicity
<input type="number" id="in" />
We're going to listen for the keypress event and do nothing if the max length is met or a period is entered, i'm using 5 as the max.
let input = document.getElementById('in');
input.addEventListener('keypress',function test(e){
if(input.value.length==5 || e.key=='.')
e.preventDefault();
});
You can run a validation check in your filterInput method.
document.querySelector('.input-group .form-control').addEventListener('keyup', function() {
var keyCode = ('which' in event) ? event.which : event.keyCode;
isNotWanted = (keyCode == 69);
if (this.value.length > this.maxLength) {
this.value = this.value.slice(0, this.maxLength);
}
return !isNotWanted;
});
<div class="col-md-3">
<div class="form-group">
<label>Customer Number</label>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-hashtag"></i></span>
<input maxlength="5" name="CustomerNumber" type="number" class="form-control" required>
</div>
</div>
<!-- /.form-group -->
</div>
<!-- /.col -->
I have implemented jQuery International Telephone Input but the issue now is, when i select the country, the prefix code doesn't show. How can i achieve this please ?
View
<div class="form-group">
<label for="eventRegInput2">Phone Number</label>
<input type="tel" id="phone" class="form-control square" placeholder="" value="{{ old('phone') }}"name="phone" required>
</div>
JS code responsible for displaying the prefix of the country selected.
JS
// get the input val, adding the dial code if separateDialCode is enabled
_getFullNumber: function() {
var val = $.trim(this.telInput.val()), dialCode = this.selectedCountryData.dialCode, prefix, numericVal = this._getNumeric(val), // normalized means ensure starts with a 1, so we can match against the full dial code
normalizedVal = numericVal.charAt(0) == "1" ? numericVal : "1" + numericVal;
if (this.options.separateDialCode) {
prefix = "+" + dialCode;
} else if (val.charAt(0) != "+" && val.charAt(0) != "1" && dialCode && dialCode.charAt(0) == "1" && dialCode.length == 4 && dialCode != normalizedVal.substr(0, 4)) {
// if the user has entered a national NANP number, then ensure it includes the full dial code / area code
prefix = dialCode.substr(1);
} else {
prefix = "";
}
return prefix + val;
},
How can I achieve this please?
Assuming that your function is working (that format properly input text with area code, all you have to do is when user leave textbox you can call your function to format number. This snippet need also to check if user has input something in textbox and if it is a valid code. Apart from that this is the way to ensure that your format function run everytime user leaves textbox and update its value with output from your function.
$('#phone').on('blur', function() {
var value = $(this).val();
if(value) {
$(this).val(_getFullNumber());
}
});
I have created a form which works out a sum depending on the users input, this works fine but during the input stage i get the infinity property displayed in the total. Is there anyway of avoiding this?
I'm by no means a Javascript expecrt so any help would be appreciated. Here is the code.
<div class="wrapper">
<form id="convert">
<input type="text" name="child" onkeyup="formChanged()" onchange="formChanged()"/>
<input type="text" name="parent" onkeyup="formChanged()" onchange="formChanged()"/>
<div id="final"></div>
</form>
<script>
function formChanged() {
var first = document.getElementsByName("child")[0].value;
var second = document.getElementsByName("parent")[0].value;
var third = first / second;
var four = third * 100;
document.getElementById("final").innerHTML = four+"%";
}
</script>
</div><!-- /.wrapper -->
Don't divide by zero.
What you want to do when second is zero is up to you. But probably the easiest way to handle it is to just not do the calculation and not write anything in final unless you have a non-zero value from second.
In addition, you might want to check for NaN as well. If somebody writes a something in either textbox that is not actually a number, you will end up with NaN% in your output. (here you can use isNaN or you can compare the results of parsing your values with NaN).
So you could do something like:
var first = parseFloat(document.getElementsByName("child")[0].value);
var second = parseFloat(document.getElementsByName("parent")[0].value);
if (first !== NaN && second) { // note NaN and 0 are both falsy
// do your calculation here
}
You're going to need to do some validation on your values first. Your calculation only makes sense with numeric values and you're going to have to ensure that you don't try to calculate it if your second variable == 0.
In this case, I wouldn't try to parse/validate the inputs. Do as few as possible, and assume valid inputs.
Just test wether you get a valid output, before showing the result.
function isValidNumber(v){
//!NaN && !Infinity
return v===v && v !== Infinity && v !== -Infinity;
}
//cast the inputs to a valid number
function number(v){
//return +String(v).replace(",", ".");
return +v;
//return +v || 0;
}
function formChanged() {
var first = document.getElementsByName("child")[0].value;
var second = document.getElementsByName("parent")[0].value;
var result = 100 * number(first) / number(second);
document.getElementById("final").innerHTML = isValidNumber(result)?
Math.floor(result) + "%": //I have a valid result
""; //values have changed, but sth. went wrong
}
I think that will work for you.
<div class="wrapper">
<form id="convert">
<input type="text" name="child" onkeyup="formChanged()" onchange="formChanged()"/>
<input type="text" name="parent" onkeyup="formChanged()" onchange="formChanged()"/>
<div id="final"></div>
</form>
<script>
function formChanged() {
var first = document.getElementsByName("child")[0].value;
var second = document.getElementsByName("parent")[0].value;
if(second == ""){second=1};
if(first != "" && second != ""){
var third = parseInt(first) / parseInt(second);
var four = parseInt(third) * 100;
document.getElementById("final").innerHTML = four+"%";
}
}
</script>
</div><!-- /.wrapper -->
Thanks
I had one row with three fields: received, issue, balance
<input type="text" name="rcv" class="rcv"/>
<input type="text" name="issue" class="issue"/>
<input type="text" name="blnc" class="balance"/>
I calculated the balance for each row easily, but how do I calculate more than one row?
Each row has receive, issue and balance fields.
How do I calculate each row's balance field?
I tried like this for multiple row but it's not working:
$('.t_rtn, .t_rcv').each(function(){
$(this).on('blur',function(){
var totalRcv = $('.t_rcv').val();
var totalRtn = $('.t_rtn').val();
// console.log( $('t_rtn').next('.consume').val() );
$('t_rtn').next('.consume').val(totalRcv-totalRtn);
});
you need to parse The value of textbox as it returns string not int
$('.t_rtn, .t_rcv').each(function(){
$(this).on('blur',function(){
var totalRcv = parseInt($('.t_rcv').val()) || 0;
var totalRtn = parseInt($('.t_rtn').val()) || 0;
// console.log( $('t_rtn').next('.consume').val() );
$('t_rtn').next('.consume').val(totalRcv-totalRtn);
});
If your code is being run on document.ready it will only be applied to elements which exist at that point.
You'd be better with :
$(document).on('blur','.t_rtn, .t_rcv',function(){
var val = $(this).val();
...
});
try this..
$(document).on('blur','.receive, .return', function()
{
var $row = $(this).closest(".row");
var totalRcv = parseInt($row.find('.receive').val()) || 0;
var totalRtn = parseInt($row.find('.return').val()) || 0;
$row.find('.balance').val(totalRcv - totalRtn);
});
In addition to parsing the string values into integers you also need to use the correct selectors for those input elements. t_rtn is not the right class name, for example. And if doing this in rows you will want to grab the correct element from the current row (you already did this correctly for the consume field)
Fixed html (Example.. I chose to use div with class name = row):
<div class='row'>
<input type="text" name="rcv" class="receive"/>
<input type="text" name="issue" class="return"/>
<input type="text" name="blnc" class="balance"/>
</div>
<div class='row'>
<input type="text" name="rcv" class="receive"/>
<input type="text" name="issue" class="return"/>
<input type="text" name="blnc" class="balance"/>
</div>
<div class='row'>
<input type="text" name="rcv" class="receive"/>
<input type="text" name="issue" class="return"/>
<input type="text" name="blnc" class="balance"/>
</div>
Fixed code:
$(document).on('blur','.receive, .return', function()
{
var $row = $(this).closest(".row");
var totalRcv = parseInt($row.find('.receive').val()) || 0;
var totalRtn = parseInt($row.find('.return').val()) || 0;
$row.find('.balance').val(totalRcv - totalRtn);
});
I took the liberty of fixing some inconsistencies with the class names used. I tried to match them up to the variables for totalRcv and totalRtn so that now the balance shows as receipt minus return. If the user enters non-numeric data, it defaults the value to 0 before calculating.
Example fiddle here: http://jsfiddle.net/cp81g4nf/1/
I think problem is because you are subtracting 2 Strings. .val returns an String.
Convert them in number before subtracting like bellow
$('t_rtn').next('.consume').val((+totalRcv)-(+totalRtn));