Counting elements doesn't work - javascript

I have a table and want to calculate each element like:
calc-this-cost * calc-this-cost(value of checkbox) = calc-this-total
Then summ all calc-this-cost and put it to totalcost div.
This is table:
<td class="params2">
<table id="calc-params">
<tr>
<td>aaa</td><td class="calc-this-cost">159964</td><td class="calc-this-count">
<input type="checkbox" name="a002" value="0" onclick="calculate(this);" />
</td><td class="calc-this-total">0</td>
</tr>
<tr>
<td>bbb</td><td class="calc-this-cost">230073</td><td class="calc-this-count">
<input type="checkbox" name="a003" value="0" onclick="calculate(this);" />
</td><td class="calc-this-total">0</td>
</tr>
<tr>
<td>ccc</td><td class="calc-this-cost">159964</td><td class="calc-this-count">
<input type="checkbox" name="a004" value="1" onclick="calculate(this);" />
</td><td class="calc-this-total">0</td>
</tr>
........
</table>
.......
</td>
<div id="calc-total-price">TOTAL COST: <span>0</span></div>
My script (in function calculate)
var totalcost=0;
$('.params2 tr').each(function(){
var count=parseFloat($('input[type=checkbox]',$(this)).attr('value'));
var price=parseFloat($('.calc-this-cost',$(this)).text().replace(" ",""));
$('.calc-this-total',$(this)).html(count*price);
totalcost+=parseFloat($('.calc-this-cost',$(this)).text());
});
$('#calc-total-price span').html(totalcost);
Counting each element and put result to calc-this-cost - work perfect.
But totalcost result NaN. Why?

[general] don't parseFloat() more than you need to
[general] move repeating code to functions
[jQuery] use .find() over context and cache nodes ($row)
[general] look at how String.replace() works
[general] look at Number.toFixed() for displaying floats
example
var totalcost = 0,
toFloat = function(value) {
// remove all whitespace
// note that replace(" ", '') only replaces the first _space_ found!
value = (value + "").replace(/\s+/g, '');
value = parseFloat(value || "0", 10);
return !isNaN(value) ? value : 0;
};
$('.params2 tr').each( function() {
var $row = $(this),
count = toFloat($row.find('.calc-this-count input').val()),
price = toFloat($row.find('.calc-this-cost').text()),
total = count * price;
$row.find('calc-this-total').text(total.toFixed(2));
totalcost += total;
});
$('#calc-total-price span').text(totalcost.toFixed(2));

console.log() will solve all your problems:
$('.params2 tr').each(function(){
var count=parseFloat($('input[type=checkbox]',$(this)).attr('value'));
var price=parseFloat($('.calc-this-cost',$(this)).text().replace(" ",""));
$('.calc-this-total',$(this)).html(count*price);
totalcost+=parseFloat($('.calc-this-cost',$(this)).text());
console.log(count, price, totalcost)
});
Add more logging where every you don't understand something. Didn't I just tell you to use logging? :)

Related

how to dynamically increment input control by JavaScript....?

I used for loop to copy the table to n times. The code below works only in first table. How can i get to work in all tables?. I am a beginner.
function copy() {
var text1 = document.getElementById("Name1").value;
document.getElementById("Name2").value = text1;
var text2 = document.getElementById("Name3").value;
document.getElementById("Name4").value = text2;
}
<td rowspan="3" style="height:100px;">Name <input type="text" name="Emp name" placeholder="enter your name" id="Name1" /><br> ID <input type="id" name="Emp Id" placeholder="enter id" id="Name3"> </td>
<tr id="p001">
<td colspan="10" style="border:1px solid #ffffff;height:150px;"><input type="button" value="Get data" onclick="copy();" /><label for="text"> Name : <input type="text" id="Name2"></label>
<label for="text"> ID : <input type="id" id="Name4"></label> </td>
</tr>
ID's should always be unique. When using duplicate ID's it will only work on the first one and ignore the rest. By pushing in the selector to the function you can reuse your function for multiple tables.
https://jsfiddle.net/m5aqdswe/
onclick="copy('Name');"
function copy(selector) {
var text1 = document.getElementById(selector + "1").value;
document.getElementById(selector + "2").value = text1;
var text2 = document.getElementById(selector + "3").value;
document.getElementById(selector + "4").value = text2;
}
Hope this helps
EDIT TO HELP WITH YOUR FIDDLE MISTAKE
After checking your code I can see that you haven't implemented my fix. You have an onclick on the button calling copy();. You're not passing in any arguments so your JS is static. So when you add another table you're creating duplicate ID's.
When searching for an ID document.getElementById("Name1") it will search through the DOM until it finds that first id="Name1" and then stop. That is why your second table never works.
To fix that we need to push in your ID name to the function so that the JS becomes dynamic. copy('Name') where "Name" is the first part of your ID. The numbers will still be used.
In the function you need to grab that arguments by passing it in to the function and calling it whatever you like. I chose 'selector' because it is most descriptive. onclick="copy(selector)"
No the function will replace all the 'selector' variables with the string you passed through, namely "Name" so document.getElementById(selector + "1") will actually be document.getElementById("Name1"). This way you can create as many clones as you like but remember to change the clone table ID's and pass in the correct argument to the onclick.
Here is your fixed fiddle. https://jsfiddle.net/3shjhu98/2/
Please don't just copy, go see what I did. You'll need to fix your clone function to use dynamic arguments instead of static ones.
function check() {
var rowCount = $('table.mytable tbody tr');
for (var index = 0; index < rowCount.length; index++) {
var tr = $('table.mytable tbody tr')[index];
var td = $(tr).find('td');
for (var j = 0; j < rowCount.length; j++) {
copy('table.mytable tbody tr[data-index=' + index + '] td[data-index=' + j + ']');
}
}
}
function copy(selector) {
var val_1 = $(selector).find('input:first').val();
$(selector).find('input:last').val(val_1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<table class="mytable">
<tbody>
<tr data-index="0">
<td data-index="0">
<input type="text" onblur="check()" />
<input type="text" />
</td>
</tr>
</tbody>
</table>
Hi. try it...
I think you need to pass table selector like [ table.className ] etc. then you find input text box and get the value this and paste into another text box.
Like this.
///it mean you pass first table row of first table data.
copy('table.className tbody tr[data-index=1] td[data-index=1]');
function copy(selector) {
var val_1 = $(selector).find('input#Name1').val();
$(selector).find('input#Name2').val(val_1);
}

handle incrementing number of array ID in duplicated form field set (regex)

I need to duplicate rows of a form ( in a table )
See jsbin here : http://jsbin.com/ExiRAMa/1/edit
The markup :
<div id="o99_the_work">
<table><tbody>
<tr>
<!-- THE ORDER -->
<td>X</td>
<td class="small-text"><span class="wpcf7-form-control-wrap submitted-file"><input type="file" name="submitted-file" value="1" size="40" class="wpcf7-form-control wpcf7-file" id="submitted-file-1"></span></td>
<td><span class="wpcf7-form-control-wrap number-of-copies"><input type="text" name="number-of-copies" value="" size="40" class="wpcf7-form-control wpcf7-text small-text" id="number-of-copies-1"></span></td>
<td><span class="wpcf7-form-control-wrap checkbox-copy-type"><span class="wpcf7-form-control wpcf7-checkbox" id="copy-type-1"><span class="wpcf7-list-item"><input type="checkbox" name="checkbox-copy-type[]" value="color"> <span class="wpcf7-list-item-label">color</span></span><span class="wpcf7-list-item"><input type="checkbox" name="checkbox-copy-type[]" value="bw"> <span class="wpcf7-list-item-label">bw</span></span><span class="wpcf7-list-item"><input type="checkbox" name="checkbox-copy-type[]" value="transperant"> <span class="wpcf7-list-item-label">transperant</span></span><span class="wpcf7-list-item"><input type="checkbox" name="checkbox-copy-type[]" value="pergament"> <span class="wpcf7-list-item-label">pergament</span></span></span></span></td>
<td><span class="wpcf7-form-control-wrap submitted-remarks"><input type="text" name="submitted-remarks" value="" size="40" class="wpcf7-form-control wpcf7-text" id="submitted-remarks-1"></span> </td>
</tr></tbody></table>
<button id="add_row">Add new</button>
</div>
The JS :
jQuery("#add_row").click(function() {
var row = jQuery("#k99_the_work tbody > tr:last"),
newRow = row.clone(true);
newRow.find("input[type=text],input[type=file]").each(function() {
var num = +(this.id.match(/\d+$/) || [0])[0] + 1;
this.id = this.id.replace(/\d+$/, "") + num;
this.name = this.id;
});
newRow.insertAfter(row);
return false;
});
As you can see from the bin, the scripts works fine on input=text and it is incrementing both the name and ID - but my problem is how to deal with the checkboxes .
I need to increment the name, ID etc , while keeping it seperate arrays checkbox-copy-type[] .
Meaning , after duplication i need checkbox-copy-type-1[], checkbox-copy-type-2[] etc
I am by no means a regex person, but I tried adding :
newRow.find("input[type=checkbox]").each(function() {
var num = +(this.id.match(/checkbox-copy-type/) || [0])[0] + 1;
// this.id = this.name.replace(/\[]/, "vv") + num;
this.id = this.name.replace(/\[]/, "") + num;// take off the brackets
this.id = this.name + "[]" ;// add the brackets again
this.name = this.id;
});
But all I get when I try this is another set of brackets e.g. checkbox-copy-type[][] ,checkbox-copy-type[][][]
You can store the item in the data portion of html (if its unique for each tr/checkbox) retrieve it that way and then increment it, then add the brackets in.
HTML
<tr data-name="myName"></tr>
javascript
newRow.find("input[type=checkbox]").each(function(x, item) {
var name = $(item).data('name'); //this give you the name if it unique
var newName = name + x + '[]' // this give final result
});
I have resolved it like so :
newRow.find("input[type=checkbox]").each(function() {
var parentid = jQuery(this).parent().parent();
var num = +(this.id.match(/checkbox-copy-type+$/) || [0])[0] + 1;
this.id = this.name.replace(/\d+/, function(val) { return parseInt(val)+1; });
this.name = this.id;
parentid.attr("id",parentid.attr("id").replace(/\d+/, function(val) { return parseInt(val)+1; }));
});

How to get the value from the before selected radio?

In my case I have lines of radioboxes, every radio has a value. This value must be calculated and the result must be placed in a DIV.
My Problem is, I can't find a way to subtract the value of the choosen radion before.
let me show you a sample markup:
<table>
<tr>
<td><input name="tools" value="20" type="radio"></td>
<td><input name="tools" value="300" type="radio"></td>
<td><input name="tools" value="1000" type="radio"></td>
</tr>
<tr>
<td><input name="addons" value="5" type="radio"></td>
<td><input name="addons" value="10" type="radio"></td>
</tr>
</table>
<div id="result"></div>
JavaScript :
var radioClick = $('input[type="radio"]');
radioClick.on('change', function(evt){
// function sub or add the price...
// here is a shortcut of the add calc version...
var price = $(this).val(),
showPrice = $('#result').text(),
endresult = parseFloat(showPrice) + parseFloat(price),
$('#result').text(endResult);
});
With checkboxes it works fine, but in case of radioboyes I don't have a click-event to identify this on I must subtract.
in the first line we see the radios name=tools. here I take at first this one with value 20.
after that the value 20 will be shown in the#result, fine. But when I take now another radio name=tools the new value will add to the 20. and that is my problem. I don't know how to find the before selected radio button to get this value and subtract it.
Try using this:
html code:
<table>
<tr>
<td><input name="tools" class="test1" value="20" type="radio"></td>
<td><input name="tools" class="test1" value="300" type="radio"></td>
<td><input name="tools" class="test1" value="1000" type="radio"></td>
</tr>
<tr>
<td><input name="addons" class="test" value="5" type="radio"></td>
<td><input name="addons" class ="test" value="10" type="radio"></td>
</tr>
javascript:
<script>
var testPrice = 0;
var test1Price = 0;
var endprice = 0;
var price ='';
$('.test').click(function(){
price = $(this).val();
testPrice = price;
endPrice = parseFloat(testPrice) + parseFloat(test1Price),
$('#result').text(endPrice);
});
$('.test1').click(function(){
var price = $(this).val();
test1Price = price;
endPrice = parseFloat(testPrice) + parseFloat(test1Price),
$('#result').text(endPrice);
});
</script>
try it's demo on http://jsfiddle.net/rxrzX/
You don't need to substract. You can just find 2 value of 2 diff radio button : tools and addons. Then just add them and write in the div
You can get radio button value by :
$('input[name=radioName]:checked').val();
I think try this :
var radioClick = $('input[type="radio"]');
radioClick.on('change', function(evt){
// function sub or add the price...
// here is a shortcut of the add calc version...
var toolsprice = $('input[name=tools]:checked').val(),
var addonsprice = $('input[name=addons]:checked').val(),
endresult = parseFloat(toolsPrice) + parseFloat(addonsprice),
$('#result').text(endResult);
});
You could use an object literal that tracks the value, using a closure:
radioClick.on('change', (function()
{
var valTracker = {},
resultDiv = $('#result');//easier on the DOM
return function(evt)
{
valTracker[this.name] = valTracker[this.name] || 0;//get old value
var endResult = parseFloat(resultDiv.text()) + parseFloat($(this).val()) - valTracker[this.name];//subtract old value, too
valTracker[this.name] = parseFloat($(this).val());//set current value
resultDiv.text(endResult);
}
}()));
The valTracker object literal tracks the current radio value (the name of the element is used as property). I've also kept a reference to the $('#result') div in the closure. That way, you don't have to query the DOM every time the callback function is called.
Try using the code below: JSFIDDLE
var radio_groups = []
$(":radio").each(function(){
if (radio_groups.indexOf(this.name) == -1){
radio_groups.push(this.name);
}
});
$('input:radio').change(function(evt){
var resultPrice = 0;
$.each(radio_groups, function(){
curPrice = $(':radio[name="' + this + '"]:checked').val();
if (!(curPrice)){
curPrice = 0;
}
resultPrice = parseInt(resultPrice) + parseInt(curPrice);
});
$('#result').text(resultPrice);
});
This will work, even if you add more radio button groups. If you want this functionality only for specific groups, define the names in the array radio_groups instead of getting them from the document.

jQuery foreach checkbox checked in tr > first td

i want to iterate through the table rows and get the id and name of each checkbox checked in each tr in the first td and save it in a new Object() called values ex: values.id, values.name
Thanks
<table>
<tr>
<td>
<input id="1" type="checkbox" name="name1" checked="checked">
</td>
<td>
Some input control 1
</td>
</tr>
<tr>
<td>
<input id="2" type="checkbox" name="name2">
</td>
<td>
Some input control 2
</td>
</tr>
</table>
Working example
aRecord is an array of objects with each object containing both the name and ID of each checked checkbox found in the table.
$(document).ready(function() {
var aRecord = [];
$('#your_table input:checkbox:checked').each(function() {
var oChkBox = {};
oChkBox.name = $(this).attr('name');
oChkBox.id = $(this).attr('id');
aRecord.push(oChkBox);
});
var i = aRecord.length;
while (i--) {
alert("Name: "+ aRecord[i].name + " ID: "+ aRecord[i].id);
}
});
http://jsfiddle.net/tracyfu/r6RMV/
var values = {};
$('tr input:checked').each(function(i) {
values[i] = [];
values[i].push($(this).attr('id'));
values[i].push($(this).attr('name'));
});
Will produce:
values = { [1, 'name1'] }
I'm leaving this solution as-is, since you specifically said you wanted to store the values in an object named values, but without knowing what you're going to do with the data, I would store the values in an array instead...

Dynamic form field extraction and calculation, how?

I have a form with variable length of dynamic field names, for instanced, item{n}, the n could be 1 or 30, and I need to calculate the subtotal of qty{n} * price{n} for each such data row, then finally sum subtotal up.
The form looks like the following:
<form>
<table name="forInstruction">
<tr><td>... </td> <td>...</td> ... more td </tr>
....
</table>
<table name="forUserinput">
<tr>
<td><input type="text" id="item1">,</td> <td><input type="text" id="qty1">,</td>
<td><input type="text" id="price1">,</td> <td>fieldX1 t1 </td> ... more td
</tr>
<tr>
<td><input type="text" id="item2">,</td> <td><input type="text" id="qty2">,</td>
<td><input type="text" id="price2">,</td> <td>fieldX2,t2 </td> ... more td
<td><input type="text" id="item3">,</td> <td><input type="text" id="qty3">,</td>
<td><input type="text" id="price3">,</td> <td>fieldX3,t3 </td> ... more td
...
</table>
<input type="button" value="Calculate subtotal and total" ... />
</form>
Notes:
a) t{n} = subtotal field.
b) as mentioned above, number of rows is unknown, it could be 1 to 30.
What I'd like to do is: calculate subtotal and total.
each subtotal = qty{n} * parseFloat(price{n})
My attempt is to loop through the entire form, I'm able to retrieve
all the values for the qty{n} field,
but I don't know how to retrieve the value of its Corresponding
Price{n}.
var fQ=0,fP=0;
st = 0;
total = 0;
for (f=0; f < document.qr.elements.length; f++) {
if (document.qr.elements[f].name.indexOf('qty')>=0) {
// alert(document.qr.elements[f].name + ' ' + document.qr.elements[f].value);
fQ = document.qr.elements[f].value;
// alert(fQ);
}
else if (document.qr.elements[f].name.indexOf('priceLabel')>=0) {
fP = document.qr.elements[f].value;
}
// what do we do here? Or this is not the good way to go?
}
Maybe, loop through the entire form isn't a good idea... only data rows in a named table? If so, how?
Many thanks in advance.
EDIT 1:
Upon advice,
new code:
var i = 0, t=0,
element;
while ((element = forms[0].elements['qty' + i])) {
var subtotal = forms[0].elements['qty' + i] * forms[0].elements['price' + i];
forms[0].elements['total' + i].value = subtotal;
t = t + parseFloat(subtotal);
alert(t);
// ...
i++;
}
forms[0].elements['totalFinal'].value = t;
but err msg:
"ReferenceError: forms is not defined". How come? Thanks.

Categories

Resources