JS/jQuery: fire onchange from a disabled/readonly input without using button - javascript

The goal is to get the total Qty for the whole year.
The user will input numbers into 3 different textboxes(Jan,Feb,Mar), then the sum will be displayed into a disabled textbox(Quarter1).
Now I have 4 instances of these knowing we have 4 quarters/year.
I can easily display the sum per quarter, by using the onchange() function attached to the textboxes.
Now I am having issues getting the sum from the 4 disabled textboxes, knowing we can't use the onchange() on it because it's disabled.
I have searched and probably getting results only when a button is used.
TLDR: I am trying to display the sum from the four disabled textboxes to another textbox automatically, without the user clicking any button(just like firing the onchange event)
I have tried this one, wherein I tried to display the value of the first quarter to the total, and not working:
$(document).ready(function() {
$('input[id$=yearlyTotal]').bind("displaytotal", function() {});
$('#qtr1').change(function() {
var mos = document.getElementsByClassName("quantityA");
var mosCount = mos.length;
var total = 0;
for (var i = 0; i < mosCount; i++) {
total = total + parseInt(mos[i].value);
}
$('input[id$=yearlyTotal]').val(total).trigger('displaytotal');
});
});
Hope it's possible, thanks in advance
EDIT: Added UI
Showing Q1 (its just the same for the 4 qtrs)
<div class="form-group col-md-6">
<label class="col-sm-1 control-label">Jan:</label>
<div class="col-sm-2 small">
<input type="number" min="0" id="col3" class="form-control input-sm monthly" data-q="q1" name="January" />
</div>
<label class="col-sm-1 control-label">Feb:</label>
<div class="col-sm-2 small">
<input type="number" min="0" id="col4" class="form-control input-sm monthly" data-q="q1" name="February" />
</div>
<label class="col-sm-1 control-label">Mar:</label>
<div class="col-sm-2 small">
<input type="number" min="0" id="col5" class="form-control input-sm monthly" data-q="q1" name="March" />
</div>
<label class="col-sm-1 control-label">Q1:</label>
<div class="col-sm-2 small">
<input type="text" min="0" id="q1" class="form-control input-sm quarter" name="q1" style="background-color: #b3dcf5;" disabled />
</div>
</div>
This is the div for the total Qty
<div class="col-md-6">
<label class="col-sm-3 control-label" id="">Total Quantity:</label>
<div class="col-sm-3 small">
<input type="text" id="final" class="form-control input-sm" name="TotalQuantity" value="0" disabled />
</div>
</div>

Method 1:
Basically, what you need to do is to trigger the change event for the disabled quarter fields programatically, using jQuery .trigger() function.
As I don't know how your HTML is structured -this why it is always recommended to provide MCVE example- I made a demo example and I've done things differently, like below:
jsFiddle 1
var monthly = $('.monthly'),
Qrt = $('.quarter');
monthly.on('change, input', function() {
var $th = $(this),
// depending on the value of the data-q attribute, we pick
// all input fields with the same data-q as an array, then
//loop through them adding their values up
q = $th.attr('data-q'),
qArray = $th.parent().children('input[data-q="' + q + '"]'),
tempSum = 0;
for (var i = 0, ln = qArray.length; i < ln; i++) {
tempSum += +$(qArray[i]).val();
}
// we pick the corresponding quarter sum field, again depending
// on the value of the data-q attritues, and update its value, then
// we trigger the change event of this quarter sum field.
$('#' + q).val(tempSum).trigger('change'); // here you trigger it
});
Qrt.on('change', function() {
var qSum = 0;
for (var i = 0, ln = Qrt.length; i < ln; i++) {
qSum += +$(Qrt[i]).val();
}
$('#final').val(qSum);
});
.monthly { width: 32%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<h3>Grand Total:</h3><input type="text" id="final" disabled><hr>
<h3>1st Q:</h3>
<input type="text" class="monthly" data-q="q1">
<input type="text" class="monthly" data-q="q1">
<input type="text" class="monthly" data-q="q1">
<br>Sum:<input id="q1" type="text" class="quarter" disabled>
<h3>2nd Q:</h3>
<input type="text" class="monthly" data-q="q2">
<input type="text" class="monthly" data-q="q2">
<input type="text" class="monthly" data-q="q2">
<br>Sum:<input id="q2" type="text" class="quarter" disabled>
<h3>3rd Q:</h3>
<input type="text" class="monthly" data-q="q3">
<input type="text" class="monthly" data-q="q3">
<input type="text" class="monthly" data-q="q3">
<br>Sum:<input id="q3" type="text" class="quarter" disabled>
<h3>4th Q:</h3>
<input type="text" class="monthly" data-q="q4">
<input type="text" class="monthly q-4th" data-q="q4">
<input type="text" class="monthly q-4th" data-q="q4">
<br>Sum:<input id="q4" type="text" class="quarter" disabled>
Method 2:
since any change you make to any .monthly field will change the corresponding value of quarter sum, and thus it'll also affect the value of the yearly sum, you don't need to capture the change event of the disabled quarter sum fields, just loop through their values and update the value of the yearly field, all should be done inside the on('change') event of the .monthly fields, like below:
jsFiddle 2
jQuery
var monthly = $('.monthly'),
Qrt = $('.quarter');
monthly.on('change, input', function() {
var $th = $(this),
q = $th.attr('data-q'),
qArray = $th.parent().children('input[data-q="' +q+ '"]'),
tempSum = 0,
qSum = 0;
for (var i = 0, ln = qArray.length; i < ln; i++) {
tempSum += +$(qArray[i]).val();
}
$('#' + q).val(tempSum);
// code below
for (var i = 0, ln = Qrt.length; i < ln; i++) {
qSum += +$(Qrt[i]).val();
}
$('#final').val(qSum);
});
Update:
For the updated HTML in the OP, replace qArray line with this one:
$th.parents('.form-group').find('input[data-q="' + q + '"]')`,
Note parents() is with "s" letter, unlike the former parent() which moves up a single level up the DOM, it does " search through the ancestors of these elements in the DOM tree and construct a new jQuery object from the matching elements ordered from immediate parent on up. ", so it travels up until we reach the matchng parent, here it is .form-group.
Then instead of children(), we use find().
jsFiddle 3

Please find the below code (Finding the total for quarter A & quarter B) for your reference. Please use same methodology for other quarters.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
/* FINDING THE QUARTER A AND QUARTER B */
function findingQuaterTotal () {
/* LOADING QUARTER A AND FINDING ITS TOTAL - STARTS */
var mosQuarterA = document.getElementsByClassName("quarterA"),
mosCountQuarterA = mosQuarterA.length,
totalQuarterA = 0,
i = 0;
for (i = 0; i < mosCountQuarterA; i++) {
totalQuarterA = totalQuarterA + parseInt(mosQuarterA[i].value);
}
/* ADDING INTO QUATER A DISABLED TEXTBOX */
$("#quarterA").val(totalQuarterA);
/* LOADING QUARTER A AND FINDING ITS TOTAL - ENDS */
/* LOADING QUARTER B AND FINDING ITS TOTAL - STARTS */
var mosQuarterB = document.getElementsByClassName("quarterB"),
mosCountQuarterB = mosQuarterB.length,
totalQuarterB = 0;
for (i = 0; i < mosCountQuarterB; i++) {
totalQuarterB = totalQuarterB + parseInt(mosQuarterB[i].value);
}
/* ADDING INTO QUARTER B DISABLED TEXTBOX */
$("#quarterB").val(totalQuarterB);
/* LOADING QUARTER B AND FINDING ITS TOTAL - ENDS */
/* TRIGGERING CHANGE EVENT IN THE DISABLED TEXTBOX WHOSE ID STARTS WITH QUARTER.*/
$("input[id^='quarter']").trigger("change");
};
/* ABOVE CHANGE TRIGGER WILL CALL BELOW EVENTS - STARTS */
$("input[id^='quarter']").change(function () { $("#final").val(parseInt($("#quarterA").val())+parseInt($("#quarterB").val()));
});
/* ABOVE CHANGE TRIGGER WILL CALL BELOW EVENTS - ENDS */
/* IF ANY VALUE CHANGES IN MONTH TEXT BOX, FLLWING FUNCTION WILL BE CALLED - STARTS */
$("input[id^='month']").on("change keyup",function () {
findingQuaterTotal();
});
findingQuaterTotal();
/* IF ANY VALUE CHANGES IN MONTH TEXT BOX, FLLWING FUNCTION WILL BE CALLED - ENDS */
});
</script>
</head>
<body>
<h2>Quater A</h2>
Jan - <input type="number" id="month1" value="6" class="quarterA"></br>
Feb - <input type="number" id="month2" value="16" class="quarterA"></br>
March - <input type="number" id="month3" value="25" class="quarterA"></br>
Quater A Total - <input type="number" id="quarterA" value="" disabled></br>
<br/><br/>
<h2>Quater B</h2>
April - <input type="number" id="month4" value="6" class="quarterB"></br>
May - <input type="number" id="month5" value="16" class="quarterB"></br>
June - <input type="number" id="month6" value="25" class="quarterB"></br>
Quater B Total - <input type="number" id="quarterB" value="" disabled></br>
Quarter A and Quarter B total - <input type="number" id="final" value="" disabled>
</body>
</html>

Related

JQuery returns NaN value while calculating multiple inputs in a row

I have a multiple input rows and all rows have a total column at the end. Now, I want to put the total result of each rows in column Total. I tried but it returns NaN value instead of total result. Attached is my view & script please help what I am missing??? Thanks
$('body').on('change', '.bgpending, .registered', function() {
var el = $(this);
var totalRow = 0;
el.closest('.dosiaPlace').find('input').each(function() {
totalRow = totalRow + parseInt($(this).val());
});
el.closest('.dosiaPlace').find('.total-row').val(totalRow);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dosiaPlace">
<div class="col-md-2">
<label>#lang('dashboard.pastyear'):</label>
<input type="number" value="0" class="form-control bgpending" name="bgpending[]" />
</div>
<div class="col-md-2">
<label>#lang('dashboard.warida'):</label>
<input type="number" value="0" class="form-control registered" name="registered[]" />
</div>
<div class="col-md-2">
<label>#lang('dashboard.total'):</label>
<input type="text" class="form-control total-row" />
</div>
</div>
Result:
The container, the .dosiaPlace, I presume, has 3 inputs: the .bgpending, the .registered, and the .total-row. Your el.closest('.dosiaPlace').find('input') finds all 3 of those, including the .total-row. But the .total-row is empty (initially), so
totalRow = totalRow + parseInt($(this).val());
for it results in
totalRow = totalRow + parseInt('');
And the empty string can't be parseInt'd (results in NaN). (You also probably don't want to be including the .total-row anyway)
Use input:not(.total-row') instead of input:
$('body').on('change', '.bgpending, .registered', function() {
var el = $(this);
var totalRow = 0;
el.closest('body').find('input:not(.total-row)').each(function() {
totalRow = totalRow + parseInt($(this).val());
});
el.closest('body').find('.total-row').val(totalRow);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-md-2">
<label>#lang('dashboard.pastyear'):</label>
<input type="number" value="0" class="form-control bgpending" name="bgpending[]" />
</div>
<div class="col-md-2">
<label>#lang('dashboard.warida'):</label>
<input type="number" value="0" class="form-control registered" name="registered[]" />
</div>
<div class="col-md-2">
<label>#lang('dashboard.total'):</label>
<input type="text" class="form-control total-row" />
</div>
Your variable get null value or NaN just asign o if it is nan or empty
if(totalRow=='' || totalRow ==NaN )
{
totalRow=0;
}

How to get sum of input values?

hello im trying to add input totals to a grand total when any input is changed. i keep getting NaN in the total box. here is my code
<div class="col-md-6">
<input type="text" placeholder="Description" class="form-control" id="d" name="description" />
</div>
<div class="col-md-1">
<input type="text" placeholder="price." class="form-control" id="q" name="itemprice"/>
</div>
<div class="col-md-1">
<input type="text" placeholder="price" class="form-control" id="itemprice" name="itemprice1"/>
</div>
<div class="col-md-2">
<input type="text" placeholder="price" class="form-control" id="itemprice" name="itemprice2" onchange="myFunction()"/>
<td>Subtotal</td>
<td class="total" id="tot" for="tot">
<input type="total" id="total">
<script type="text/javascript">
function myFunction()
{
var answer = document.getElementById('total');
var x = document.getElementsByName('itemprice');
var y = document.getElementsByName('itemprice1');
var z = document.getElementsByName('itemprice2');
var d = document.getElementsByName('itemprice3');
answer.value = x.value + y.value + z.value + d.value;
}
</script>
Use Id's (fix duplicate id, remove reference to itemprice3 as it doesn't exist in the HTML). Convert text values to numbers before adding.
<div class="col-md-6">
<input type="text" placeholder="Description" class="form-control" id="d" name="description" />
</div>
<div class="col-md-1">
<input type="text" placeholder="price." class="form-control" id="itemprice" name="itemprice"/>
</div>
<div class="col-md-1">
<input type="text" placeholder="price" class="form-control" id="itemprice1" name="itemprice1"/>
</div>
<div class="col-md-2">
<input type="text" placeholder="price" class="form-control" id="itemprice2" name="itemprice2" onchange="myFunction()"/>
<td>Subtotal</td>
<td class="total" id="tot" for="tot">
<input type="total" id="total">
<script type="text/javascript">
function myFunction()
{
var answer = document.getElementById('total');
var x = document.getElementById('itemprice');
var y = document.getElementById('itemprice1');
var z = document.getElementById('itemprice2');
//var d = document.getElementsById('itemprice3');
// parseFloat converts to values, otherwise you'll concatenate the strings.
answer.value = parseFloat( "0" + x.value ) + parseFloat("0" + y.value) + parseFloat("0" + z.value); // + d.value;
document.getElementsByName returns a nodelist (because multiple nodes can have the same name). (That's why the name contains Elements with an 's' as opposed to getElementById, which returns 1 element at most.
Such a list doesn't have a value. You would either get the value of each element, or if you know it will always be one, get the value of the first element:
var y = document.getElementsByName('itemprice1')[0].value
But note, you don't have any elements that have the name itemprice3, so document.getElementsByName('itemprice3') will return a nodelist with 0 items. The line above will fail in that case.
Also note, you have two elements with id itemprice, which is illegal.
When that works, you will need parseInt() to convert the values to integers.
answer.value = parseInt(x.value) + parseInt(y.value) + parseInt(z.value) + parseInt(d.value);
If the inputs can contain floating point values as well, use parseFloat instead of parseInt.
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt

auto calculate without clicking any button

Hi I'm new for programming and I'm facing one problem.
I have 3 input for values and 1 input for total. What I need is when I change the value in any input total should change automatically.
<input type="text" name="Amt" id="amount" class="form-control" />
<input type="text" name="Amt" id="amount" class="form-control" />
<input type="text" name="Amt" id="amount" class="form-control" />
And for total I have:
<input type="text" class="form-control" name="total" id="total" value="" />
And below is the script:
<script type="text/javascript">
$('#amount').change(function() {
$('#total').attr('value', function() {
var result = 0;
$('#amount').each(function() {
result += $(this).attr('value');
});
return result;
});
});
</script>
You have multiple ids for amount. These should be changed to classes. In addition, the value for each amount will be picked out by jQuery as a string, so that needs to be changed to an integer:
$('.amount').change(function () {
var result = 0;
$('.amount').each(function () {
result += +$(this).val();
});
$('#total').val(result);
});
Fiddle.

Add and remove inputs dynamicly with a other input

I searched a lot for this, but I can only find +1 -1 solutions.
But I want to set the number of inputs with a other input like this:
//Enter the number of inputs (1 is the start-value)
<input type="text" size="3" maxlength="3" id="count" name="count" value="1">
//Display that number of inputs (1 at start)
<input type="text" size="30" maxlength="30" id="input_1" name="input_1">
When the user now writes 5 in the first field, the form should look like this:
//Enter the number of inputs (1 is the start-value)
<input type="text" size="3" maxlength="3" id="count" name="count" value="1">
//Display that number of inputs (1 at start)
<input type="text" size="30" maxlength="30" id="input_1" name="input_1">
<input type="text" size="30" maxlength="30" id="input_2" name="input_2">
<input type="text" size="30" maxlength="30" id="input_3" name="input_3">
<input type="text" size="30" maxlength="30" id="input_4" name="input_4">
<input type="text" size="30" maxlength="30" id="input_5" name="input_5">
How can I make this? MUST I use js?
Here's a simple javascript snippet that doesn't make use of any frameworks:
function addInputs() {
var count = parseInt(document.getElementById("count").value);
for (var i = 2; i <= count; i++) {
document.getElementById('moreinputs').innerHTML += '<input type="text" name="input_' + i + '" id="input_' + i + '" />';
}
}
In this example you have to add a container (div) with id 'moreinputs'. However, when calling this function more than once, it will not work properly (e.g. it can only increase the number of input but not decrease)
Yes, either you use javascript, or you send the form to the server, where a new html page with all the inputs is generated (e.g. with PHP).
Yes you must use js to do it dynamically on the spot You have a jQuery tag so I will show an example in jQuery
This is not the best example but it works and it's a starting point
JS:
$(function(){
$('#master').on('change', function() {
var count = $(this).val();
$('#otherInputs').html('')
for( var i = 0; i < count; i++) {
$('#otherInputs').append(
$('<input>', {type: 'text'})
);
}
});
});
HTML:
<input type="number" id="master" value="1">
<div id="otherInputs"></div>
Demo
In English this is saying...
When you change #master I will empty #master (html('')) loop through and append a new input depending on #master's value
Here's the FIDDLE. Hope it helps. :)
html
<input type="text" size="3" maxlength="3" id="count" name="count" value="1">
<div id="container"></div>
script
$('#count').on('keyup', function () {
var $this = $(this);
var count = $this.val();
$('#container').empty();
for (var x = 1; x <= count; x++) {
var newInput = '<input type="text" size="30" maxlength="30" id="input_' + x + '" name="input_' + x + '">';
$('#container').append(newInput);
}
});
This worked for me
function AddField() {
var count = $("#countetfield").val();
var i = 1;
var id = $("#container .testClass:last").attr('name');
var test = id.split("_");
id_name = test[1];
while (i <= count) {
id_name++;
var a = '<input type="text" class="testClass" size="30" maxlength="30" id="input_' + id_name + '" name="input_' + id_name + '"/>';
$("#container").append(a);
i++;
}
}
<input type="text" id="countetfield" value="1" />
<input type="button" value="Go" onclick="AddField();" />
<div id="container">
<input type="text" class="testClass" size="30" maxlength="30" id="input_1" name="input_1" />
</div>

2 name attributes for a field in a form

I have a script that calculates the values in each and shows the calulated values. At the end it also calculates the already calculated values from all div's
Here is the html code:
<td>
<div>
<input name="r" class="rate" type="text" maxlength="255" size="5" value />
<input name="p" class="pack" type="text" maxlength="255" size="5" value />
<span class="amount"></span>
</div>
</td>
<td>
<div>
<input name="r" class="rate" type="text" maxlength="255" size="5" value />
<input name="p" class="pack" type="text" maxlength="255" size="5" value />
<span class="amount"></span>
</div>
</td>
The problem is that I want to put all fields in a form and then submit them to a database.
However, all divs contain two input fields with name "r" and "p".
So, I am kind of stuck here because I cannot figure out how to make the names unique or how to have them passed to the DB using POST.
This is what the calculating script looks like:
<script type="text/javascript">//<![CDATA[
//any time the amount changes
$(document).ready(function() {
$('input[name=r],input[name=p]').change(function(e) {
var total = 0;
var $row = $(this).parent();
var rate = $row.find('input[name=r]').val();
var pack = $row.find('input[name=p]').val();
total = parseFloat(rate * pack);
//update the row total
$row.find('.amount').text(total);
var total_amount = 0;
$('.amount').each(function() {
//Get the value
var am= $(this).text();
console.log(am);
//if it's a number add it to the total
if (IsNumeric(am)) {
total_amount += parseFloat(am, 10);
}
});
$('.total_amount').text(total_amount);
});
});
//isNumeric function Stolen from:
//http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric
function IsNumeric(input) {
return (input - 0) == input && input.length > 0;
}
//]]>
</script>
HTML:
<input type="text" name="r[]">
<input type="text" name="p[]">
<hr>
<input type="text" name="r[]">
<input type="text" name="p[]">
<hr>
<input type="text" name="r[]">
<input type="text" name="p[]">
PHP:
for ($i = 0; $i < count($_POST['p']); $i++) {
$rate = $_POST['r'][$i];
$pack = $_POST['p'][$i];
// do something with $rate and $pack
}
Since the browser submits all inputs (even if no value has been entered) and by specification it submits them in the order they are defined in the HTML code, you can rely that the elements in the two $_POST arrays will line up and the corresponding rate and pack will be received at the same index in the respective array.

Categories

Resources