Issue on calling Javascript function twice results called once - javascript

I am working on a project that requires a form be built. The form has a function that sums up the columns as well as the rows. I am strictly using HTML and JavaScript. I am unable to get the JavaScript function called twice, once for the row and once for the column (I will actually be calling it 3 times as I need to do section totals as well). I have created different classes for the column controls that will need summed up and a different class for the row controls that will need to be summed up, hence the two different classes in the input control. I also believe that it could be in the for loop as I commented it out and put used an alert statement and it seemed to work perfectly. See the following code:
JavaScript:
<script type="text/JavaScript">
function CalcSum(displayIn, calcClass){
var sum = 0;
var displayCell = displayIn;
className = calcClass;
var divs = document.getElementsByClassName(className);
var args = [];
for (var i = 0; i <=divs.length; i++){
args.push(divs[i].value);
val = divs[i].value;
sum += val*1;
document.getElementById(displayCell).value = sum;
dollarAmount("Form1", displayCell);
}
}
HTML Control:
<input type="text" name="ctl_001" value="" id="ctl_001" class="col4txrev col4" onchange="CalcSum('T1_TOT_C4_TXREV','col4txrev');CalcSum('T1_TOT_C4','col4');" style= "width: 100%">

You have multiple errors in your script technically and functionally based on my understanding of your question.
I have corrected the errors and can see the console printing the log twice when they called.
Note: Anyways, don't call the function twice from the inline attribute. Create another function which will do the same and call it from the onchange event (or) create the onchange listener programmatically.
When looping the elements, condition should be i < divs.length and
not i <= divs.length
To find a text inside the div, it should be innerHTML as below
and not value. value can be used for the form input elements
which values can be changed by the end users.
To calculate the sum, the value should be converted to a number
using either parseInt or parseFloat since the text/value of
the element is generally a text.
If you have to assign the final value of the sum to another div
element and call another method, it should be outside the for
loop. But if you really need this to set/call for each loop, then it
can be inside the for loop.
function CalcSum(displayIn, calcClass){
var sum = 0;
var displayCell = displayIn;
var className = calcClass;
console.log('called');
var divs = document.getElementsByClassName(className);
var args = [];
for (var i = 0; i < divs.length; i++){
//args.push(divs[i].value);
var val = divs[i].innerHTML;
args.push(val);
sum += parseInt(val) * 1; // It can be parseFloat
}
document.getElementById(displayCell).value = sum;
dollarAmount("Form1", displayCell);
}
// dummy function
function dollarAmount(form, elm){
}
<input type="text" name="ctl_001" value="" id="ctl_001" class="col4txrev col4" onchange="CalcSum('T1_TOT_C4_TXREV','col4txrev');CalcSum('T1_TOT_C4','col4');" style= "width: 100%">
<div class="col4txrev">10</div>
<div id="T1_TOT_C4_TXREV"></div>
<div class="col4">20</div>
<div id="T1_TOT_C4"></div>

Related

How to add onclick functions in an array of buttons using a for loop properly?

I'm making a kind of HTML calculator to test something I have in mind.
I've used a for loop to create the buttons of the keypad. The display is a text field.
Then I used a for loop to add the functions in the buttons:
for (var i = 0; i < 10; i++)
{
buttons[i].onclick = function()
{
display.value += i;
};
}
What I was trying to do is to make, for example, buttons[0] add "0" to the value of the text field when clicked. Instead, clicking any button added "10" in the text field. Why? How can I make it right?
You almost got it right , you just need to change var to let in your loop declaration :
for (let i = 0; i < 10; i++)
{
buttons[i].onclick = function()
{
display.value += i;
};
}
What's the difference between using "let" and "var"? Here you can get more info about your issue.
Your problem is that you are referencing i directly in your functions that you are binding to your Buttons. i will actually continue to exist even after you bound all your events, and its value will be the last value of the iteration 10. So whenever a click function runs, it looks up i and finds the last value you set (10) and takes that value. What you want to do is add a constant reference instead - so that you bind that value you have during the loop and keep that reference forever, no matter how i might change later.
for (var i = 0; i < 3; i++) {
const localValue = i
buttons[i].onclick = function()
{
counter += localValue;
counterElement.innerHTML = counter
};
}
I created a small example fiddle here: https://jsfiddle.net/4k8cds9n/ if you run this you should see the buttons in action. Some related reading for this topic would be around scopes in javascript, one good article: https://scotch.io/tutorials/understanding-scope-in-javascript

innerHTML not working inside event handler function (Javascript)

I have created a function, updatePrice, which I have tied to the "click" event on the checkbox and radio buttons in my HTML form. Each checkbox and radio basically represents an item, with it's price as the value property of these <input> elements. When I check or uncheck any box, the function fires, loops through all elements in the form, and updates the total price of all the checked items into a div element I have below my form, with the id tag "priceOutput".
The following code works perfectly, printing out: The price of this item is $(price of item).
function updatePrice() {
var price = 0
for (i=0;i<=form.length;i++) {
var element = form[i]
if(element.checked) {
price+=parseInt(element.value)
}
document.getElementById("priceOutput").innerHTML = "The price of this item is $" + price + "."
}
}
But, if I switch the the last line around, the line is not printed at all:
function updatePrice() {
var price = 0
for (i=0;i<=form.length;i++) {
var element = form[i]
if(element.checked) {
price+=parseInt(element.value)
}
}
document.getElementById("priceOutput").innerHTML = "The price of this item is $" + price + "."
}
Why must I write the line in the {} of the for in order to work. Doesn't the price variable's scope extend over the entire updatePrice function?
I'm still rather new to programming, so do forgive me if this is an elementary question.
It seems to me that it isn't printing because you are causing an error. Since array indexing starts at 0 your for loop should not use <= but rather < :
for (i=0;i<form.length;i++) {
...
}
The reason why nothing gets printed then is because on the last loop the function errors and you setting the inner HTML never gets executed.
Seems like there is an error with your code, how about adding var to your for loop and removing the = from i<=form.length
for (var i = 0; i < form.length; i++)

How to have a dynamic variable in a function without linking it to a changing variable [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
sorry for the title but I'm not sure what the correct terminology is for this issue. I am trying to dynamically generate a table of clickable elements using for loops in JavaScript. Each of the elements, when clicked, should trigger the same function but with different parameters. In my code I am setting the onClick function up like so:
elementArray[i].onClick = function() { clickFunction(i) };
However, when I do this the clickFunction is just taking whatever value i is currently set to, not what it was when I set the onClick function, which is what I want. Any ideas?
As I got your question you want a table having clickable element calling to same function with diff param. [Let me know if it's not your question]
So taking i (index or row no.) would be param to that function.
HTML :
<table id='myTable'></table>
Javascript :
for(i = 9; i >= 0; i--) {
var table = document.getElementById("myTable");
// Create an empty <tr> element and add it to the 1st position of the table:
var row = table.insertRow(0);
// Insert new cells (<td> elements) at the 1st and 2nd position of the "new" <tr> element:
var cell = row.insertCell(0);
// Add some text to the new cells:
cell.innerHTML = "<input type='button' onclick='callIt("+i+")'";
}
function callIt(index) {
alert(index);
}
I am considering that you want button to click.
Hope it will help you.
more you can get on w3schools
Here's a version of #Bhojendra Nepal's "duplicate question" applied to your question. With this HTML:
<div class="element-0">0</div>
<div class="element-1">1</div>
<div class="element-2">2</div>
And this script:
var elementArray = [];
var creatFunc = function($this,i){
return function() {
console.log(i);
$this.html(i + 1);
if (i>1) i++;
};
};
for (var i = 0; i < 3; i++) {
elementArray[i] = $('.element-' + i);
elementArray[i].click( creatFunc( elementArray[i] , i) );
}
by creating the functions in a separate function, we've isolated the variable. I added "if (i>1) i++;" to show how the new function keeps its own variable and can increment it (keep clicking on the third div to see the number keep increasing).
here's a jsfiddle:
https://jsfiddle.net/mckinleymedia/1cksb8ky/
I hope this helps.
Oh, I added jQuery to this. I'm not positive how to get this working in vanilla javascript off hand.

Multiply an element by a number and insert using jQuery

I'm wondering if you can multiply an element using jQuery a number of times and insert it using .html()?
I am building my own slider which might help put things in context...
I am getting a number of times an element is used, which is stored in a var called eachSlideCount. So for example, this might output 10.
Then what I want to do is create a <span></span> for each of these (so 10 spans) and insert this into a div to generate a pager.
$this.next('.project-slider-count').html('<span></span>')
Is there anyway to muliply this span by the eachSlideCount number and then add to the .project-slider-count element?
I got this far... but clearly missing something...
var eachSlideCount = $this.find('.other-slides').length;
var eachSlideTotal = ($this.next('.project-slider-count').html('<span></span>')) * eachSlideCount;
$('.project-slider-count').html(eachSlideTotal);
Thanks in advance
Multiplication can only be done on numbers. If you want to repeat something, write a loop:
var span = '';
for (var i = 0; i < eachSlideCount; i++) {
span += '<span></span>';
}
$this.next('.projectslider-count').html(span);
In JavaScript, you can execute a for loop. For example, in the following:
var count = 10;
for (var i=0; i<count; i++) {
// Code
}
The body of the loop would be executed 10 times.
In jQuery, you can append a new HTML element inside an existing element using the append() method. For example, the following will add <span> elements in a loop:
var container = $("#container");
var count = 10;
for (var i=0; i<count; i++) {
container.append("<span>");
}
This is illustrated in a jsFiddle.

Jquery sum of inputs from table

Im trying to get the sum of an input from a table. Currently I have:
HTML:
<tr id='saved1'>
<td><input class='qty'/></td>
<td><input class='price'/></td>
<td><input class='subtotal'/></td>
</tr>
Jquery:
//COUNT ALL FIELDS
function calculateSum() {
$("[id^=saved]").each(function() {
sum = $(this).parent().parent().find('.qty').val() * $(this).parent().parent().find('.price').val();
$(this).parent().parent().find('.subtotal').val(sum);
});
}
// On change
$("input").change(calculateSum);
Any Ideas?
Your DOM traversal is wrong. You don't need to go up to the parents, you just need to find the elements in that row.
function calculateSum() {
$("[id^=saved]").each(function() {
var sum = $(this).find('.qty').val() * $(this).find('.price').val();
if (!isNaN(sum)) {
$(this).find('.subtotal').val(sum);
}
});
}
If the rows are being added dynamically, you need to use event delegation for the binding:
$("#tableID").on('change', 'input', calculateSum);
DEMO
Okay, so your code has a variety of problems (I believe the transversal was wrong, and you are multiplying rather than adding, and you aren't checking for not a numbers/NaNs), and I'm going to address as many as I can.
The cascading style of organization was very hard to read. Using variables can be much easier to read and debug. As you can see, I declared multiple variables with one var declaration. Use var. It makes variables local rather than global, so you can define sum somewhere else without messing up your original functions.
You also try adding 2 unchecked inputs together. As you can see I'm using the bitwise operator:
qty = grandparent.find('.qty').val() | 0,
This returns 0 if qty isn't an integer. This is important, otherwise it will assume the inputs are strings, and append one, rather than adding them together.
I would also strongly recommend you avoid tags such as $("[id^=saved]"). Selecting by attributes can be very costly/slow. Not something to worry about immediately, but you see how I avoided using that selector below. You generally want to use an id, class, tag or variable as your selector.
function calculateSum() {
var $this = $(this),
grandparent = $(this).parent().parent(),
qty = grandparent.find('.qty').val() | 0,
price = grandparent.find('.price').val() | 0,
sum = qty + price;
$('.subtotal').val(sum);
}
// On change
$("input").change(calculateSum);
Working fiddle
JSBIN
function foo(){
foo.total += $(this).val() - 0;
}
function calcField(selector){
foo.total = 0;
$(selector).each(foo)
$(selector+'total').val(foo.total);
}
function calcFields(){
var fields = [".qty",".price",".subtotal"];
for(var i in fields){
calcField(fields[i]);
}
}
$('button').on('click',calcFields);

Categories

Resources