Calculation with many fields - javascript

I have 4 fields for me to do the calculation, they should add up together and give me the total sum. However, there are some problems with fields when it is empty.
The code and script is below:
<tr id="row">
<td>No. of Dependant(s)</td>
<td><input type="text" id="Dep-main" value="0"></td>
<td><input type="text" id="Dep-joint1" value="0"></td>
<td><input type="text" id="Dep-joint2" value="0"></td>
<td><input type="text" id="Dep-joint3" value="0"></td>
<td><input type="text" id="Total-dep" readonly></td>
</tr>
The script:
<script>
var main = document.getElementById("Dep-main");
var joint1 = document.getElementById("Dep-joint1");
var joint2 = document.getElementById("Dep-joint2");
var joint3 = document.getElementById("Dep-joint3");
var total = document.getElementById("Total-dep");
1
var inputs = Array.prototype.slice.call(document.querySelectorAll("td > input"));
inputs.forEach(function (input) {
input.addEventListener("blur", function () {
// Always supply the second argument to parseInt() (the radix) so you
// dont' get non-base 10 answers.
if (main.value.length === 0) {
total.value = parseFloat(joint1.value) + parseFloat(joint2.value) + parseFloat(joint3.value);
} else if (joint1.value.length === 0) {
total.value = parseFloat(main.value) + parseFloat(joint2.value) + parseFloat(joint3.value);
} else if (joint2.value.length === 0) {
total.value = parseFloat(main.value) + parseFloat(joint1.value) + parseFloat(joint3.value);
} else if (joint3.value.length === 0) {
total.value = parseFloat(main.value) + parseFloat(joint1.value) + parseFloat(joint2.value);
}else{
total.value = parseFloat(main.value) + parseFloat(joint1.value) + parseFloat(joint2.value) + parseFloat(joint3.value);
}
});
});
</script>
However, if there is 2 or more fields are empty, the Total field will appear NaN. Is there any way for me to keep the field as empty and get the total number?

My original idea was flawed in that it would not update the final value if a field was subsequently cleared of a value. Using an object to maintain the values for any element that has received the blur event and then performing a sum calculation of the values seems to work OK.
var total = {};
/* returns numeric value of field or zero if empty etc */
function fieldvalue(id){
var field=document.getElementById( id );
return field.value!='' && field.value.length > 0 && !isNaN( parseFloat( field.value ) ) ? parseFloat( field.value ) : 0;
}
var col=document.querySelectorAll('tr#row > td > input:not([readonly])');
if( col ){
for( var n in col )if( col[ n ].nodeType==1 ){
col[n].addEventListener('blur',function(event){
total[ this.id ]=fieldvalue( this.id );
document.getElementById('Total-dep').value=Object.values(total).reduce(function(a,b){return a+b;});
}.bind( col[n] ),false);
}
}
or, more akin to the original code using Array.prototype.slice
/*
The aim here is to select all input elements that are not marked
as "readonly" as it is these that will be used for the calculations
whilst the "readonly" field is updated programmatically only.
*/
var col=document.querySelectorAll('tr#row > td > input:not([readonly])');
/*
Convert array-like object into a true array in order that we can use
Array.forEach() method which does not work for all browsers when dealing
with HTMLCollections - such as a nodelist
*/
var inputs = Array.prototype.slice.call( col );
inputs.forEach(function(e){
/*
Assign the `onblur` event handler to each of the input elements
- the callback to the event handler will update the `total` object
which is then later processed to calculate the sum of values stored.
*/
e.addEventListener('blur',function(event){
/*
Update the total object with field value
*/
total[ this.id ]=fieldvalue( this.id );
/*
Update the "readonly" field with calculated sum of values
*/
document.getElementById('Total-dep').value=Object.values( total ).reduce(function(a,b){return a+b;});
}.bind( e ),false);
});
Perhaps worth noting is the use of Object.values(obj) - it is not supported by all browsers ( IE, Opera & Safari for instance ) but there are polyfills available here and here
And, I just wrote this - not stringently tested btw
if( typeof( Object.values )!='function' ){
Object.prototype.values=function(obj){
var tmp=[];
var keys=Array.prototype.slice.call( Object.keys( obj ) );
keys.forEach(function( item ){
tmp.push( obj[item] )
});
return tmp;
};
}

i would loop the fields, and if contains something add it.
total.value = 0;
if (main.value.length === 0) {
total.value += parseFloat(main.value);
}
if (join1.value.length === 0) {
total.value += parseFloat(join1.value);
}
if (join2.value.length === 0) {
total.value += parseFloat(join2.value);
}
if (join3.value.length === 0) {
total.value += parseFloat(join3.value);
}

I did not get what you are really after. However, I believe using such checks will lead you to the solution:
var x = $("#someFloatExpectedInput").val();
var y = $("#someIntExpectedInput").val();
if (!isNaN(parseFloat(x))) {
//
}
if (!isNaN(parseInt(y))) {
//
}

You are checking null value in if else statement that why you are getting the error so you need to check separately
Just do like this
var total=0;
if (main.value.length != 0) {
total = total+parseFloat(main.value);
}
if (joint1.value.length != 0) {
total = total+parseFloat(joint1.value);
}
if (joint2.value.length != 0) {
total = total+parseFloat(joint2.value);
}
if (joint3.value.length != 0) {
total = total+parseFloat(joint3.value);
}
total.value = total
It will help you to solve our issue.

Related

how to replace input numbers with commas after key presses

I want to replace a number over 100 with commas. Like 1000 to 1,000 and 1000000 to 1,000,000 etc. in HTML. I have found the code on here to do so but it only works with predetermined numbers being passed. I don't want it to work for a predetermined number but for any number typed into the box.
<label for="turnover">Estimated Monthly Card Turnover:</label><br />
<span>£ </span><input type="text" id="turnover" maxlength="11"
name="turnover" size="10" required>*
<br /><br />
<script type="text/javascript">
$('#turnover').keydown(function(){
var str = $(this).val();
str = str.replace(/\D+/g, '');
$(this).val(str.replace(/\B(?=(\d{3})+(?!\d))/g, ","));});
</script>
I created a solution using pure javascript.
function onChange(el) {
var newValue = el.value.replace(/,/g, '');
var count = 0;
const last = newValue.substring(newValue.length - 1, newValue.length); // last input value
// check if last input value is real a number
if (!isNumber(last)) {
el.value = el.value.substring(0, el.value.length - 1);
return;
}
newValue = newValue.split('')
.reverse().map((it) => {
var n = it;
if (count > 0 && count % 3 == 0) n = n + ',';
count++;
return n;
})
.reverse().join('')
el.value = newValue
// document.getElementById('value').innerHTML = newValue
}
function isNumber(input) {
return input.match(/\D/g) == undefined;
}
<label>Number</label>
<input id="numbers" onkeyup="onChange(this)">
There are a couple of issues with your code:
It runs once when the page loads, not after that. I added a button to fix that.
The id used in your code does not match the actual id of the input field.
Input fields must be read and written using .val(). .text() works only for divs, spans etc.
Note that the conversion now works one time, after that it fails to properly parse the new text which now contains the comma(s).
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function ShowComma() {
console.clear();
var val = parseInt($("#comma").val());
console.log(val);
val = numberWithCommas(val);
console.log(val);
$("#comma").val(val);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="turnover">Estimated Monthly Card Turnover:</label><br />
<span>£ </span><input type="value" id="comma" maxlength="30" name="turnover" size="10" required>*
<button onclick="ShowComma()">Show Comma</button>
To finalise this I have putgetElementById functions in so that this will work with a wordpress contact form 7. This must be with a text field though as it will not work with the number field as it will now accept commas:
<script>
document.getElementById("averagetrans").onkeyup = function() {onChange(this)};
document.getElementById("Turnover").onkeyup = function() {onChange(this)};
</script>
<script type="text/javascript">
function onChange(el) {
var newValue = el.value.replace(/,/g, '');
var count = 0;
const last = newValue.substring(newValue.length - 1, newValue.length); // last input value
// check if last input value is real a number
if (!isNumber(last)) {
el.value = el.value.substring(0, el.value.length - 1);
return;
}
newValue = newValue.split('')
.reverse().map((it) => {
var n = it;
if (count > 0 && count % 3 == 0) n = n + ','; // put commas into numbers 1000 and over
count++;
return n;
})
.reverse().join('')
el.value = newValue
// document.getElementById('value').innerHTML = newValue
}
function isNumber(input) {
return input.match(/\D/g) == undefined;
}
</script>

jquery does not support mask,any altenative? [duplicate]

I want to mask the text in an input box without changing the actual value. I can not use any plugins.
I am currently doing this - but as you can see the issue is that the actual value is changed on submit. How can I just change the display value?
$("input[name='number']").focusout(function(){
var number = this.value.replace(/(\d{2})(\d{3})(\d{2})/,"$1-$2-$3");
this.value = number;
}
You need two inputs
Two inputs should get the job done. One input will contain the masked text and the other will be a hidden input that contains the real data.
<input type="text" name="masknumber">
<input type="text" name="number" style="display:none;">
The way I approached the masking is to build a function for both masking and unmasking the content so everything stays uniform.
$("input[name='masknumber']").on("keyup change", function(){
$("input[name='number']").val(destroyMask(this.value));
this.value = createMask($("input[name='number']").val());
})
function createMask(string){
return string.replace(/(\d{2})(\d{3})(\d{2})/,"$1-$2-$3");
}
function destroyMask(string){
return string.replace(/\D/g,'').substring(0,8);
}
Working JSFiddle
or also
<input type="text" onkeypress="handleMask(event, 'data: 99/99/9999 99:99 999 ok')" placeholder="data: ok" size=40>
with
function handleMask(event, mask) {
with (event) {
stopPropagation()
preventDefault()
if (!charCode) return
var c = String.fromCharCode(charCode)
if (c.match(/\D/)) return
with (target) {
var val = value.substring(0, selectionStart) + c + value.substr(selectionEnd)
var pos = selectionStart + 1
}
}
var nan = count(val, /\D/, pos) // nan va calcolato prima di eliminare i separatori
val = val.replace(/\D/g,'')
var mask = mask.match(/^(\D*)(.+9)(\D*)$/)
if (!mask) return // meglio exception?
if (val.length > count(mask[2], /9/)) return
for (var txt='', im=0, iv=0; im<mask[2].length && iv<val.length; im+=1) {
var c = mask[2].charAt(im)
txt += c.match(/\D/) ? c : val.charAt(iv++)
}
with (event.target) {
value = mask[1] + txt + mask[3]
selectionStart = selectionEnd = pos + (pos==1 ? mask[1].length : count(value, /\D/, pos) - nan)
}
function count(str, c, e) {
e = e || str.length
for (var n=0, i=0; i<e; i+=1) if (str.charAt(i).match(c)) n+=1
return n
}
}
A more robost version of accepted answer without having two input's which may pollute transmitted form fields and also being aware of key-repetitions and other quirks when pressing a key too long:
<input type="text" name="masknumber" data-normalized="">
and
$("input[name='masknumber']").on("input", function(){ // input event!
let n = destroyMask(this.value);
this.setAttribute("data-normalized", n); // saved as attribute instead
this.value = createMask(n);
})
function createMask(string){
return string.replace(/(\d{2})(\d{3})(\d{2})/,"$1-$2-$3");
}
function destroyMask(string){
return string.replace(/\D/g,'').substring(0, 7); // 7 instead of 8!
}
JSFiddle

balancing two input number fields in jquery

I would like to balance two input number fields using jquery based on the max value set for both. for example its like a balance, if one side goes down the other goes up and vice versa. another example if the max value is 20 then if i enter 5 in input field one then 15 would be left in input field two.
Need the help Thanks. Haven't started coding it as yet stuck trying to figure it out.
First you need to attach the input eventhandler on all of the relevant input fields. This event handler will compare the current input value of a input fields to the total/max value variable and find the remainder accordingly. The event handler then finds the other input fields and assigns them with the appropriate remainder values.
Note: This allows you to add as many inputs as you want and it will
balance them all out. Just remember to add the balance class on the
input field.
var total = 20;
$('.balance').on('input', function() {
var value = parseInt(this.value);
if (isNaN(value)) {
this.value = value = 0;
} else if (value > total) {
this.value = value = total;
}/* else if (value < 0) {
this.value = value = 0;
}
* Remove this comment if value shouldn't be negative.
*/
var remainder = total - value;
var otherInputs = $('.balance');
otherInputs.splice($.inArray(this,otherInputs),1);
var remainderDiv = remainder/otherInputs.length;
$.each(otherInputs, function(input) {
otherInputs[input].value = remainderDiv;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="balance">
<input type="number" class="balance">
Update: The two inputs can be less than the max but never higher.
var max = 20;
$('.balance').on('input', function() {
var value = parseInt(this.value);
if (isNaN(value)) {
value = 0;
}
var otherInputs = $('.balance');
var sum = 0;
$.each(otherInputs, function(input) {
sum += parseInt(otherInputs[input].value);
});
if (sum > max)
this.value = max - (sum - value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="balance">
<input type="number" class="balance">
here's a fiddle to get you started (and maybe finished):
https://jsfiddle.net/ahmadabdul3/xwyrrw53/1/
html:
<input type='number' id='first' class='balancable'/>
<input type='number' id='second' class='balancable'/>
js:
$(function() {
var max = 20;
var balanceOpposite = {
'first': 'second',
'second': 'first',
}
$('.balancable').on('input', function() {
var id = $(this).attr('id');
var thisVal = $(this).val();
$('#' + balanceOpposite[id]).val(20 - thisVal);
});
});

javascript numbers from HTML Textbox

I have 2 HTML textboxes and need to convert them to numbers so I can perform a calculation but I am just getting NaaN. My code is:
Where totalcost is html textbox
and pg is also a html textbox
document.getElementById("totalcost").value = parseFloat(document.getElementById("pg").value) + parseFloat(document.getElementById("totalcost").value);
I want the totalcost box to be populated by "totalcost + pg" as it is a click and add cart system. Why Float, its for bitcoin.
Try this:
// get the `pg` value and attempt to convert to a Number, otherwise default to 0.00
var pg = Number(document.getElementById("pg").value) || 0.00;
// get the `totalcost` value and attempt to convert to a Number, otherwise default to 0.00
var totalCost = Number(document.getElementById("totalcost").value) || 0.00;
// update the `totalcost` element to include the sum of `pg` and `totalcost`
document.getElementById("totalcost").value = pg + totalCost
Added some comments to help explain each step.
Lets do that:
function isNumeric(n) {
/* http://stackoverflow.com/a/1830844/603774 */
return !isNaN(parseFloat(n)) && isFinite(n);
}
function calc() {
var
d_1 = document.getElementById('d_1').value,
d_2 = document.getElementById('d_2').value,
result;
/* Validation for d_1 */
if (!isNumeric(d_1)) {
alert('d_1 is not a number');
return;
}
/* Validation for d_2 */
if (!isNumeric(d_2)) {
alert('d_2 is not a number');
return;
}
result = +d_1 + +d_2;
alert('Result: ' + result);
}
<input type="text" id="d_1"> + <input type="text" id="d_2"> <input type="button" value="calculate" onclick='calc()'>
Use the unary plus operator with or conditional
document.getElementById("totalcost").value = (+(document.getElementById("pg").value) || 0) + (+(document.getElementById("totalcost").value) || 0);

Allow to select only predifened combination from available values

let us say we have parameter with A,B,C and D values. Now we want to force the user to choose only A,B,C or A,C,D or A or B or C.
Instead of Allowing all possible 16 combination, we want to allow only 5 predefined combination. I tried it but for this i have to put condition for each and every selection.
If we assume this values are bind with checkbox and we need to check whether selected values are as per our predifined combination or not.
I need to achieve this in javascript or either angular.js. Please help me with proper algorithm for such operation.
I tried below logic to achieve this but this will not infor user instantly, alert only after final submission
// multi-dimentional array of defined combinations
var preDefinedCombinations = [['a','b','c'], ['a','c','d'], ['a'], ['b'], ['c']];
// Combination user select
var selectedvalues = [];
// Function called on selection or removing value (i.e a,b,c,d)
function selectOption(value){
var checkIndex = selectedvalues.indexof(value);
if(checkIndex == -1){
selectedvalues.push(value);
}else{
selectedvalues.splice(checkIndex, 1);
}
}
// function called on submition of combination
function checkVaildCombination(){
if(preDefinedCombinations.indexOf(selectedvalues) == -1){
alert('Invalid Combination');
}else{
alert('Valid Combination');
}
}
This code gives information only about combination is valid or not, not about which may be possible combinations as per selections.
stolen from https://stackoverflow.com/a/1885660/1029988 :
function intersect_safe(a, b)
{
var ai=0, bi=0;
var result = new Array();
while( ai < a.length && bi < b.length )
{
if (a[ai] < b[bi] ){ ai++; }
else if (a[ai] > b[bi] ){ bi++; }
else /* they're equal */
{
result.push(a[ai]);
ai++;
bi++;
}
}
return result;
}
then in your code:
function checkVaildCombination(){
function get_diff(superset, subset) {
var diff = [];
for (var j = 0; j < superset.length; j++) {
if (subset.indexOf(superset[j]) == -1) { // actual missing bit
diff.push(superset[j]);
}
}
return diff;
}
if(preDefinedCombinations.indexOf(selectedvalues) == -1){
missing_bits = [];
diffed_bits = [];
for (var i = 0; i < preDefinedCombinations.length; i++) {
var intersection = intersect_safe(preDefinedCombinations[i], selectedvalues);
if (intersection.length == selectedvalues.length) { // candidate for valid answer
missing_bits.push(get_diff(preDefinedCombinations[i], intersection));
} else {
var excess_bits = get_diff(selectedvalues, intersection),
missing_bit = get_diff(preDefinedCombinations[i], intersection);
diffed_bits.push({
excess: excess_bits,
missing: missing_bit
});
}
}
var message = 'Invalid Combination, if you select any of these you`ll get a valid combination:\n\n' + missing_bits.toString();
message += '\n\n Alternatively, you can reach a valid combination by deselected some bits and select others:\n';
for (var j = 0; j < diffed_bits.length; j++) {
message += '\ndeselect: ' + diffed_bits[j].excess.toString() + ', select: ' + diffed_bits[j].missing.toString();
}
alert(message);
} else {
alert('Valid Combination');
}
}
you will of course want to format the output string, but that code will (hopefully, it is napkin code after all) give you the missing bits to make valid combos with what you've got selected already
May be following code could help you to solve ur problem
<script>
function validateForm(){
var checkBoxValues = this.a.checked.toString() + this.b.checked.toString() + this.c.checked.toString() + this.d.checked.toString();
if( checkBoxValues == 'truetruetruefalse' || // abc
checkBoxValues == 'truefalsetruetrue' || // acd
checkBoxValues == 'truefalsefalsefalse' || // a
checkBoxValues == 'falsetruefalsefalse' || // b
checkBoxValues == 'falsefalsetruefalse' ){ // c
return true;
}
return false;
}
</script>
<form onsubmit="return validateForm()" action="javascript:alert('valid')">
<input type="checkbox" name="mygroup" id="a">
<input type="checkbox" name="mygroup" id="b">
<input type="checkbox" name="mygroup" id="c">
<input type="checkbox" name="mygroup" id="d">
<input type="submit">
</form>

Categories