Trying to loop through all the inputs, when more are added, and add them all to the total (var = paidTotal). I'm getting NaN for the total and Cannot read property 'length' of undefined. Pretty sure the issue is in the peoplepaid() function.
In the peoplePaid() onclick function I'm trying to loop through all the fieldInputs (class="person") depending on how many inputs are created and add the total to #paidTotal. Hopefully that's helpful.
$(document).ready(function() {
var maxFields = 20;
var addButton = $('#plusOne');
var deleteButton = $('#minusOne');
var wrapper = $('#userNumbers');
var fieldInput = '<div><input type="text" name="persons" class="persons"/></div>';
var x = 1;
$(addButton).click(function() {
if (x < maxFields) {
x++;
$(wrapper).append(fieldInput);
}
});
$(deleteButton).click(function(e) {
e.preventDefault();
var myNode = document.getElementById("userNumbers");
i = myNode.childNodes.length - 1;
if (i >= 0) {
myNode.removeChild(myNode.childNodes[i]);
x--;
}
});
});
function peoplePaid() {
var checkTotal = document.getElementById('check').value;
var personsCheck = document.getElementsByClassName('persons').value;
var inputs = document.getElementsByClassName('persons');
var paidTotal = document.getElementById('paidTotal');
for (var i = 1; i < personsCheck.length; i += 1) {
paidTotal[i] += personsCheck;
}
paidTotal.innerHTML = checkTotal - personsCheck;
}
<h3>Check Total</h3>
$ <input type="text" id="check" value="" />
<h3>Number of People: <span id="numberOfPeople"></span></h3>
<button type="button" onclick="plusOne()" id="plusOne">+</button>
<button type="button" onclick="minusOne()" id="minusOne">-</button>
<div>
<div id="userNumbers">
<input type="text" class="persons" name="person">
</div>
</div>
<button onclick="peoplePaid()">Calculate</button>
<!--Paid Amount-->
<div>
<h3>Paid Amount: <span id="paidTotal"></span></h3>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
The reason you are getting Cannot read property 'length' of undefined is because
var personsCheck = document.getElementsByClassName('persons').value;
will return undefined.
document.getElementsByClassName('persons')
will return an array of DOM elements and arrays do not have a value property. Then when you access
personsCheck.length
in the loop you get Cannot read property 'length' of undefined because personsCheck is undefined.
I refactored a bit but I used map to get an array of the values then summed them up using reduce
run the snippet below
$(document).ready(function() {
const maxFields = 20;
const wrapper = $('#userNumbers');
const fieldInput = '<div><input type="text" name="persons" class="persons"/></div>';
const reducer = (a,c) => parseInt(a,10) + parseInt(c,10);
$('#plusOne').click(() =>
$("#userNumbers .persons").length < maxFields &&
$(wrapper).append(fieldInput));
$('#deleteButton').click(()=> $("#userNumbers .persons").last().remove());
$('#peoplePaid').click( () => {
const arr= $("#userNumbers .persons").map(function(){
return $(this).val();
}).get();
$('#paidTotal').html(arr.reduce(reducer));
})
});
<h3>Check Total</h3>
$ <input type="text" id="check" value="" />
<h3>Number of People: <span id="numberOfPeople"></span></h3>
<button type="button" id="plusOne">+</button>
<button type="button" id="minusOne">-</button>
<div>
<div id="userNumbers">
<input type="number" class="persons" name="person">
</div>
</div>
<button id="peoplePaid">Calculate</button>
<!--Paid Amount-->
<div>
<h3>Paid Amount: <span id="paidTotal"></span></h3>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Related
(ETA: I'm working on this for a class and the teacher wants everything to be "oninput"...yes, it's annoying :p )
I'm working on a form where each function miltiplies a number and gives me a "subtotal" on input. I'd like to take the two "subtotal" answers from the two functions and add them togething into a "total" amount. I feel like this should be simple but nothing I've tried works.
Here's what I've got in the javascript that works to give me the two subtotals:
function myCalculator() {
var qty1 = document.getElementById('qty1').value;
document.getElementById('subTotalOne').innerHTML = '$ ' + qty1 * 19.99;
}
function myCalculatorTwo() {
var qty2 = document.getElementById('qty2').value;
document.getElementById('subTotalTwo').innerHTML = '$ ' + qty2 * 37.99;
}
Here's the important parts of the html:
<div class="qty">
<label for="qty">Qty</label><br>
<input type="number" id="qty1" placeholder="0" oninput="myCalculator()"/><br>
<input type="number" id="qty2" placeholder="0" oninput="myCalculatorTwo()"/><br>
</div>
<div class="price">
<label for="price">Price</label>
<p>$19.99</p>
<p>$37.99</p>
</div>
<div class="subtotal">
<label for="subTotal">Total</label><br>
<span class="subTotalOne" id="subTotalOne">$</span><br>
<span class="subTotalTwo" id="subTotalTwo">$</span><br>
</div>
<div class="total">
<label for="total">Order Total</label><br>
<span class="orderTotal" id="orderTotal" oninput="orderTotal()">$</span><br>
</div>
I'm trying to add the subTotalOne and subTotalTwo and have them output at orderTotal, essentially. :)
Thanks!
//Global variables (concidering ID is unique)
let subTotalOne, subTotalTwo, qty1, qty2, orderTotal;
const setup = () => {
subTotalOne = document.getElementById('subTotalOne');
subTotalTwo = document.getElementById('subTotalTwo');
qty1 = document.getElementById('qty1');
qty2 = document.getElementById('qty2');
orderTotal = document.getElementById('orderTotal');
myCalculator();
myCalculatorTwo();
};
const updateTotal = (target, value) => {
if(target == null || value == null || Number.isNaN(value)) return;
target.textContent = `$ ${value.toFixed(2)}`;
target.setAttribute('data-value', value.toFixed(2));
}
const getTotal = () => {
if(subTotalOne == null || subTotalTwo == null) return 0;
const [value1, value2] = [
Number.parseFloat((subTotalOne.dataset?.value ?? 0), 10),
Number.parseFloat((subTotalTwo.dataset?.value ?? 0), 10)
];
if(Number.isNaN(value1) || Number.isNaN(value2)) return;
else return value1 + value2;
};
const updateOrderTotal = () => updateTotal(orderTotal, getTotal());
const myCalculator = () => {
const value = Number.parseFloat(qty1.value || 0, 10) * 19.99;
updateTotal(subTotalOne, value);
updateOrderTotal();
}
const myCalculatorTwo = () => {
const value = Number.parseFloat(qty2.value || 0, 10) * 37.99;
updateTotal(subTotalTwo, value);
updateOrderTotal();
}
window.addEventListener('load', setup);
<div class="qty">
<label for="qty">Qty</label><br>
<input type="number" id="qty1" placeholder="0" oninput="myCalculator()" min="0"><br>
<input type="number" id="qty2" placeholder="0" oninput="myCalculatorTwo()" min="0"><br>
</div>
<div class="price">
<label for="price">Price</label>
<p data-value="19.99">$19.99</p>
<p data-value="37.99">$37.99</p>
</div>
<div class="subtotal">
<label for="subTotal">Total</label><br>
<span class="subTotalOne" id="subTotalOne">$</span><br>
<span class="subTotalTwo" id="subTotalTwo">$</span><br>
</div>
<div class="total">
<label for="total">Order Total</label><br>
<span class="orderTotal" id="orderTotal" oninput="orderTotal()">$</span><br>
</div>
Here's how you do it:
function orderTotal() {
const qty1 = document.getElementById('qty1').value;
const qty2 = document.getElementById('qty2').value;
const total = parseInt(qty1) + parseInt(qty2);
document.getElementById('orderTotal').innerHTML = '$ ' + total;
}
Remove the oninput="orderTotal()" in your span element and trigger the above function using a button click e.g. <button onClick="orderTotal()">Calculate Total</button> or maybe when either of your two inputs' value changes. Also consider using const and let instead of var.
https://www.freecodecamp.org/news/var-let-and-const-whats-the-difference/
Instead of querying the DOM in Ray's answer--as DOM queries should generally be avoided since they are slow W3 Wiki, you could also consider using a shared variable between the two functions.
Also, consider using something else in place of innerHTML, mostly because of efficiency why-is-element-innerhtml-bad-code.
var total1;
var total2;
function myCalculator() {
var qty1 = document.getElementById('qty1').value;
total1 = qty1 * 19.99
document.getElementById('subTotalOne').textContent = '$ ' + total1;
}
function myCalculatorTwo() {
var qty2 = document.getElementById('qty2').value;
total2 = qty2 * 37.99;
document.getElementById('subTotalTwo').textContent = '$ ' + total2;
}
function orderTotal() {
document.getElementById('orderTotal').innerHTML = '$ ' + (total1 + total2);
//parentheses because '$' isn't a number so the numbers total1 and total2 will be treated like strings and joined together
}
I have written the code of taking input value from a text box and adding it to an array using the add button and also displaying the values of the array when the display button is clicked.
The thing is I did all this using JavaScript and now I want to do it using jQuery. I tried a code snippet from this website but it's not working. Please help.
<body>
<script src="jquery-3.3.1.js"></script>
<input type="text" id="text1"></input>
<input type="button" id="button1" value="Add" onclick="add_element_to_array();"></input>
<input type="button" id="button2" value="Display" onclick="display_array();"></input>
<div id="Result"></div>
<script>
var x = 0;
var sample = []; // <-- Define sample variable here
function add_element_to_array(){
$(document).on('click', '#btnSubmit', function () {
var test = $("input[name*='i_name']");
$(test).each(function (i, item) {
sample.push($(item).val());
});
console.log(sample.join(", "));
});
}
function display_array() {
var e = "<hr/>";
for (var y = 0; y < sample.length; y++) {
e += "Element " + y + " = " + sample[y] + "<br/>";
}
document.getElementById("Result").innerHTML = e;
}
</script>
</body>
You can use this code to get idea of how it should work. You can also check for non-empty value before pushing the value into the array as an empty value in array will not make any sense.
$(document).ready(function(){
var valueArray = [];
//add value in array
$('#button1').click(function(){
var textValue = $('#text1').val();
//push non empty value only
if(textValue.trim() !== ''){
valueArray.push(textValue);
//reset the text value
$('#text1').val('');
}
});
//display value
$('#button2').click(function(){
$('#Result').html(valueArray.toString());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="text1"></input>
<input type="button" id="button1" value="Add"></input>
<input type="button" id="button2" value="Display"></input>
<div id="Result"></div>
I have added the jquery script considering the following as your suggested html.
<input type="text" id="text1"></input>
<input type="button" id="button1" value="Add"></input>
<input type="button" id="button2" value="Display"></input>
<div id="Result"></div>
The inptArr must be a global array.
<script>
var inptArr = [];
$('#button1').on('click',function(){
if($('#text1').val() != '')
inptArr.push($('#text1').val());
});
$('#button2').on('click',function(){
var string = '';
var lastIndex = parseInt(inptArr.length - 1);
for(var i = 0; i <= lastIndex ; i++)
{
if(i == lastIndex)
string += inptArr[i];
else
string += inptArr[i] + ',';
}
$('#Result').append(string);
});
</script>
This is another way to achieve what you want with minor changes.
You have only one text input element so don't need any each loop.
document.ready() is needed if you define script from starting of the code because at starting there is no defined element that have an id as btnSubmit so this block must wait to dom elements to be ready.
Also you don't need pure javascript code getElementById on display_array() function when you use jquery. You can change it as $("#Result").html(e);
var x = 0;
var array = [];
$(document).ready(function(){
$('#btnSubmit').on('click', function () {
array.push($("#text1").val());
});
});
function display_array() {
var e = "<hr/>";
for (var y = 0; y < array.length; y++) {
e += "Element " + y + " = " + array[y] + "<br/>";
}
$("#Result").html(e);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="text1"/>
<input type="button" id="btnSubmit" value="Add"/>
<input type="button" id="button2" value="Display" onclick="display_array();"/>
<div id="Result"></div>
In your code functions passed to onclick attributes are binding the click event to a DOM - don't do that.
var array = Array();
var input = $("#text1");
var result = $("#result");
function add_element_to_array(){
var value = input.val();
array.push(value);
console.log("Add:", value);
// input.val(""); // bonus: clears input after adding text to an array
}
function display_array() {
result.text(array.toString());
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="text1">
<input type="button" id="button1" value="Add" onclick="add_element_to_array();">
<input type="button" id="button2" value="Display" onclick="display_array();">
<div id="result"></div>
I have this simple piece of code:
var numb1 = document.getElementById("numb1")
var numb2 = document.getElementById("numb2")
var numb3 = document.getElementById("numb3")
var numb4 = document.getElementById("numb4")
var v1 = parseInt(numb1)
var v2 = parseInt(numb2)
var v3 = parseInt(numb3)
var v4 = parseInt(numb4)
var t = parseInt(0)
function myFunction() {
if (numb1.checked == true) {
var t = v1 + t
} else if (numb2.checked == true) {
var t = v2 + t
} else if (numb3.checked == true) {
var t = v3 + t
} else if (numb4.checked == true) {
var t = v4 + t
}
document.getElementById("demo").innerHTML = t
}
<input id="numb1" type="radio" value="10">
<input id="numb2" type="radio" value="50">
<input id="numb3" type="radio" value="80">
<input id="numb4" type="radio" value="120">
<button type="button" onclick="myFunction()">Submit</button>
<p id="demo"></p>
I get that I definitely could have been more efficient when making my variables, but my problem is that even after I use parseInt() to go from string to integer, the end result in demo displays NaN. Is there something wrong with the way I defined the variables, or is it the calculation of the end value?
Because parseInt( elementObject ) doesn't return a valid number.
You wanted to parse the value, with a radix
var v1 = parseInt(numb1.value, 10);
And you have to get those values inside the function, when the value has actually changed.
Also, add some semicolons, they aren't always needed, but it's good practice to add them, and don't redeclare variables
var numb1 = document.getElementById("numb1");
var numb2 = document.getElementById("numb2");
var numb3 = document.getElementById("numb3");
var numb4 = document.getElementById("numb4");
function myFunction() {
var v1 = parseInt(numb1.value, 10);
var v2 = parseInt(numb2.value, 10);
var v3 = parseInt(numb3.value, 10);
var v4 = parseInt(numb4.value, 10);
var t = 0;
if (numb1.checked) {
t = v1 + t;
} else if (numb2.checked) {
t = v2 + t;
} else if (numb3.checked) {
t = v3 + t;
} else if (numb4.checked) {
t = v4 + t;
}
document.getElementById("demo").innerHTML = t
}
<input id="numb1" type="radio" value="10">
<input id="numb2" type="radio" value="50">
<input id="numb3" type="radio" value="80">
<input id="numb4" type="radio" value="120">
<button type="button" onclick="myFunction()">Submit</button>
<p id="demo"></p>
I agree with the answer by adeneo. The issue is that you are parseInting an HTML Input Element.
And you already got the answer.
But I noticed that you use if..else
So, You want only one value to be selected by the user.
So, There is a short method which also help to improve the loading speed and reduce lines of codes.
using forms
function myFunction(){
t=parseInt(document.forms[0]["num"].value);
document.getElementById("demo").innerHTML=t
}
<form>
<input id="numb1" name="num" type="radio" value="10">
<input id="numb2" name="num" type="radio" value="50">
<input id="numb3" name="num" type="radio" value="80">
<input id="numb4" name="num" type="radio" value="120">
<button type="button" onclick="myFunction()">Submit</button>
</form>
<p id="demo"></p>
I am trying to put form content in a JSON dynamically.
It worked before, but after I added a extra layer (arrays in arrays) there seem to be something that I am doing wrong:
aJSON = {};
aJSON['properties'] = [];
aJSON['options'] = [];
aJSON['arrays'] = [];
$('input').each(function () {
if($(this).attr('name') != undefined) {
if($(this).attr('name').indexOf('[]') > -1) {
if(aJSON['arrays'][$(this).attr('name')] == undefined) {
aJSON['arrays'][$(this).attr('name')] = [];
}
if($(this).is(':checked')) {
aJSON['arrays'][$(this).attr('name')][$(this).attr('value')] = 1;
} else {
aJSON['arrays'][$(this).attr('name')][$(this).attr('value')] = 0;
}
} else {
aJSON['properties'][$(this).attr('name')] = $(this).val();
}
}
});
$('select').each(function () {
if($(this).attr('name') != undefined) {
aJSON['properties'][$(this).attr('name')] = $(this).val();
}
});
var array = getUrlVars();
aJSON['options']['type'] = array['type'];
aJSON['options']['id'] = array['id'];
aJSON['options']['view'] = pageSpecificVariables['view'];
The top 4 lines are just a tryout, I also tried:
aJSON = {'properties':[], 'options':[], 'arrays':[]}
But the only result I am getting is an object with empty arrays of properties, options and arrays.
Before I put all the values directly in aJSON and that worked perfectly.
But for categorizing, I need the 3 categories to exist.
Any idea why my values aren't written to the aJSON?
EDIT
Added JSfiddle here: http://jsfiddle.net/abayob/pob32fs1/
I assume you are trying to serialise a form.
Use jQuery's serializeArray function instead
var myform = $("#myform");
var data = JSON.stringify( myform.serializeArray() );
Update
Because you're trying to use arrays like object-maps
Solution: http://jsfiddle.net/pob32fs1/8/
var oJSON = {
properties: {},
options: {},
arrays: {}
};
$('input[name]').each(function(){
var $el = $(this),
value = $el.attr("value"),
name = $el.attr('name');
if(name.indexOf('[]') >= 0)
{
oJSON.arrays[name] = oJSON.arrays[name] || {};
oJSON.arrays[name][value] = $el.is(':checked') ? 1 : 0;
} else {
oJSON.properties[name] = $el.val();
}
});
$('select[name]').each(function(){
var $el = $(this);
oJSON.properties[$el.attr('name')] = $el.val();
});
oJSON.options['type'] = 'user';
oJSON.options['id'] = 1;
oJSON.options['view'] = 'user-settings';
console.log(oJSON);
Assuming that the name and value attributes of your various inputs are strings, and not just numbers, you should be using nested objects, not nested arrays. You're trying to use associative arrays, which are not available in JavaScript.
var oJSON = {};
$('._save, .btn-success').click(function() {
oJSON = {
properties: {},
options: {},
arrays: {}
};
$('input').each(function() {
if ($(this).attr('name') != undefined) {
if ($(this).attr('name').indexOf('[]') > -1) {
if (oJSON['arrays'][$(this).attr('name')] == undefined) {
oJSON['arrays'][$(this).attr('name')] = {};
}
if ($(this).is(':checked')) {
oJSON['arrays'][$(this).attr('name')][$(this).attr('value')] = 1;
} else {
oJSON['arrays'][$(this).attr('name')][$(this).attr('value')] = 0;
}
} else {
oJSON['properties'][$(this).attr('name')] = $(this).val();
}
}
});
$('select').each(function() {
if ($(this).attr('name') != undefined) {
oJSON['properties'][$(this).attr('name')] = $(this).val();
}
});
oJSON['options']['type'] = 'user';
oJSON['options']['id'] = 1;
oJSON['options']['view'] = 'user-settings';
console.log(oJSON);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="tab-content">
<div id="tab-general" class="tab-pane active">
<h4>Gebruikersnaam</h4>
<input type="text" value="John Doe" name="username" class="form-control" required="" placeholder="J. Average">
<h4>E-mailadres</h4>
<input type="email" value="info#info.info" name="mailaddress" class="form-control" required="" placeholder="E-mail#adres.nl">
<div class="row">
<div class="col-md-6">
<input type="password" name="password" minlength="10" class="form-control" placeholder="Nieuw wachtwoord">
</div>
<div class="col-md-6">
<input type="password" name="password_retype" minlength="10" class="form-control" placeholder="Herhaal wachtwoord">
</div>
</div>
<input type="password" name="password_old" class="form-control margin-y-10" placeholder="Huidig Wachtwoord">
</div>
<div id="tab-sites" class="tab-pane">
<h4>Websites</h4>
<div id="site_container">
<div class="checkbox block">
<input name="sites[]" checked="" type="checkbox" value="0">
<label>A</label>
</div>
<div class="checkbox block">
<input name="sites[]" checked="" type="checkbox" value="1">
<label>B</label>
</div>
<div class="checkbox block">
<input name="sites[]" checked="" type="checkbox" value="2">
<label>C</label>
</div>
</div>
</div>
</div>
<div class="panel-footer">
<button type="button" class="btn btn-warning _cancel">Annuleren</button>
<button type="button" class="btn btn-success _save">Opslaan</button>
</div>
I have this script I'm working on and there's no errors on it but I want to add some functions on it like when I click the button it adds but I want the name attribute of the input text to be changed too.
Here's my script:
javascript:
var a = 1;
function add() {
var fContent = document.getElementById('1');
var sContent = document.getElementById('2');
if (a <= 10) {
a++;
var objTo = document.getElementById('m');
var divtest = document.createElement("div");
divtest.innerHTML = (sContent.innerHTML + a + fContent.innerHTML);
alert(divtest.innerHTML);
objTo.appendChild(divtest);
}
}
html:
<input type="button" onclick="add();" value="+" />
<div id="m">
<div id="1">
<input type="text" name="f">
<input type="text" name="l">
<input type="text" name="m">
</div>
<div id="2"></div>
</div>
OUTPUT:
2
<input type="text" name="f">
<input type="text" name="l">
<input type="text" name="m">
EXPECTED OUTPUT:
2
<input type="text" name="f2">
<input type="text" name="l2">
<input type="text" name="m2">
and so on...
You're not doing anything to change the name attributes. Trying to make those changes with html concatenation will get you into trouble. This will get you started:
(function() {
var a = 1;
// get a reference to the container
var container = document.getElementById("m");
// get a reference to the first row of input
var base = container.children[0];
document.querySelector("button").addEventListener("click", function(e) {
if(++a > 10) return;
// clone the first row of input
var clone = base.cloneNode(1);
// change the number text by setting the span's textContent
clone.children[0].textContent = a;
// set the names of the input fields
clone.children[1].name = "f" + a;
clone.children[2].name = "l" + a;
clone.children[3].name = "m" + a;
// add the new row to the container
container.appendChild(clone);
console.log(clone);
});
})();
<button type="button">+</button>
<div id="m">
<div><span>1</span><input type="text" name="f1"><input type="text" name="l1"><input type="text" name="m1"></div>
</div>
If you'd rather create the elements from scratch...
(function() {
var a = 1;
// get a reference to the container
var container = document.getElementById("m");
var input;
var span;
var div;
document.querySelector("button").addEventListener("click", function(e) {
if(++a > 10) return;
// create our div
div = document.createElement("div");
// create and append our span
span = document.createElement("span");
span.textContent = a;
div.appendChild(span);
// create and append inputs
["f","l","m"].forEach(function(n){
input = document.createElement("input");
input.name = n + a;
div.appendChild(input);
});
// append our div
container.appendChild(div);
console.log(div);
});
})();
<button type="button">+</button>
<div id="m">
<div><span>1</span><input type="text" name="f1"><input type="text" name="l1"><input type="text" name="m1"></div>
</div>