Sum Values of Dynamic Content - javascript

Given that I have 5 input fields that are linked to their own price, I want to be able to grab the value of the input multiplied by its specific price and return that value to the dom.
This is what's being rendered, there are 5 with a unique price.
I'm not sure how to link each input to its specific price, add the prices of all 5 inputs (if there are any) and post them on the dom.
I'm trying to get the data-price of the .class p tag, loop through them, link it to their input add the sum and post the sum to the dom
<section data-itemid="${menuObj.id}">
<div class="amount">
<input type="number" placeholder="Quantity" min="0" name="${menuObj.id}">
</div>
<div class="item">
<h1>${menuObj.name}</h1>
<p class="food">${menuObj.description}</p>
<p class="price" data-price="${menuObj.price}">${menuObj.price}</p>
</div>
</section>
I have it working for one, but not sure how to get them working for all
$(function() {
$('input').on('keyup', function() {
var input = $('.amount input').val();
var price = $('.price').data('price');
var final = $('.finalprice p');
var total = input * price;
final.text(total);
});
})

For dynamic content use event delegation to bind events.
$(document).on('input', '.menu-class div[class="amount"] input[type="number"]', function() {...}
Use input event to cover every change on your input Quantity.
Apply a class to the section. i.e: .menu-class
Approach
Basically, loop over the section and collect the amount.
var total = 0;
$('.menu-class').each(function() {
var $section = $(this);
var input = $section.find('div.amount [type="number"]').val();
var price = $section.find('.price').data('price');
total += (input * price);
});
$finalPrice.text(total);
Snippet
$(function() {
var $finalPrice = $('.finalprice p');
$finalPrice.on('calculate', function() {
var total = 0;
$('.menu-class').each(function() {
var $section = $(this);
var input = $section.find('div.amount [type="number"]').val();
var price = $section.find('.price').data('price');
total += (input * price);
});
$finalPrice.text(total);
});
$(document).on('input', '.menu-class div[class="amount"] input[type="number"]', function() {
$finalPrice.trigger('calculate');
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class='col-md-6 col-xs-6'>
<section class='menu-class' data-itemid="111">
<div class="amount">
<input type="number" placeholder="Quantity" min="0" name="quant_111">
</div>
<div class="item">
<h1>My Meat :-)</h1>
<p class="food">Meat</p>
<p class="price" data-price="1000.0">1,000.00</p>
</div>
</section>
<hr>
<section class='menu-class' data-itemid="112">
<div class="amount">
<input type="number" placeholder="Quantity" min="0" name="quant_112">
</div>
<div class="item">
<h1>My bread :-)</h1>
<p class="food">Bread</p>
<p class="price" data-price="2000.0">2,000.00</p>
</div>
</section>
</section>
<section class='col-md-6 col-xs-6'>
<section class='finalprice'>
<h1>Final price</h1>
<p>
</p>
</section>
</section>

$('.amount input') returns an array-like object of all dom elements that match the selector. I believe $('.amount input').val(); will return value from the first item in the array
You may want to localize finding inputs, like below:
$(function() {
$('input').on('keyup', function() {
var $section = $(this).closest('section');
var input = $section.find('.amount input').val();
var price = $section.find('.price').data('price');
var final = $section.find('.finalprice p');
var total = input * price;
final.text(total);
});
});

Related

JS - Calculate price depending on span/div fields

I have a form, where a user can select between different options inside a few dropdown fields. Depending on the user selection, the values will be displayed inside a span field next to the dropdown field.
Now I would like to count all those values inside the span fields, so that I can display a total amount at the end of the form before it will be submitted.
Here is a part of my form:
<form name='formname_form' action='./index.php' method='post' class='formname-form' id='formname-form'>
<div class="row" id='save_prices'>
<div class="col-lg-8 offset-lg-2 col-md-10 offset-md-1 col-sm-12">
<div class="form-inline">
<label class="form-icon">
<figure>
<img src="../assets/images/symbol-1.png" alt="/">
</figure>
</label>
<div class="form-group">
<select name="field_a" id="field_a" onchange="CalcDiscount()">
<option value="0,00">Option A?</option>
<option value="6,17">Yes</option>
<option value="0,00">No</option>
</select>
</div>
<div class="amount-wrap-3">
<span>€ <span id='field_a_price' class='prices'></span></span>
</div>
</div>
<div class="form-inline">
<label class="form-icon">
<figure>
<img src="../assets/images/symbol-2.png" alt="/">
</figure>
</label>
<div class="form-group">
<select name="field_b" id="field_b" onchange="CalcDiscount()">
<option value="0,00">Option B</option>
<option value="17,50">Yes</option>
<option value="0,00">No</option>
</select>
</div>
<div class="amount-wrap-3">
<span>€ <span id='field_b_price' class='prices'></span></span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8 offset-lg-2 col-md-10 offset-md-1 col-sm-12">
<div class="total-amount">
Total Price
<div class='price'><span id='total_price' class="total_price"></span> €</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-xs-12">
<div class="form-inline">
<input name='submit' type='submit' id='submit' value='Save' class='btn btn-form-indiv'/>
</div>
</div>
</div>
</form>
And here is my javascript part:
<script>
// Get references to the objects you need (<select> and <span>)
var field_a = document.getElementById('field_a');
var field_a_price = document.getElementById('field_a_price');
var field_b = document.getElementById('field_b');
var field_b_price = document.getElementById('field_b_price');
// When the list value changes, set the innerHTML of the <span>
field_a.onchange = function() {
field_a_price.innerHTML = this.value;
};
field_b.onchange = function() {
field_b_price.innerHTML = this.value;
};
var priceList = $('#save_prices').find('.prices');
var totalPrice = 0;
$.each(priceList, function(i, price){
totalPrice += parseInt($(price).text())
});
$('.total_price').text(totalPrice);
</script>
Does anyone have an idea what I am doing wrong? The value inside my span with the class total_price stays always 0. I assume that is has something to do with my onChange methods that I am using?
Problem
The total from the 2 select boxes are not appearing in the Total Price area.
Solution
Create a function and call it to fire off on the onchange event when a new value is selected in the selection boxes.
Example
// Get references to the objects you need (<select> and <span>)
var field_a = document.getElementById('field_a');
var field_a_price = document.getElementById('field_a_price');
var field_b = document.getElementById('field_b');
var field_b_price = document.getElementById('field_b_price');
// When the list value changes, set the innerHTML of the <span>
field_a.onchange = function() {
field_a_price.innerHTML = this.value;
// Calling new function
updateTotal();
};
field_b.onchange = function() {
field_b_price.innerHTML = this.value;
// Calling new function
updateTotal();
};
// New function
function updateTotal() {
var p = $('.prices').map(function () { return $(this).text(); }).get();
var totalPrice = 0;
$.each(p, function( index, value ) {
totalPrice = totalPrice + value;
$('.total_price').text(totalPrice);
});
}
Summary
I am not sure what you are attempting to do with the values considering they have commas.
To directly address your question, when your code is ran the reason the values are always empty is because all the code only runs on page load. When you change the selection box values only the code in the onchange was being ran. By adding a function that is called each time a selection is made we can populate the array from the class list returned with JQuery.

Trying to remove each line of HTML element using a newly created button

var Operator = document.getElementById("operation");
var Desc = document.getElementById("description");
var Amount = document.getElementById("value");
var budget = 0.00;
var income = 0.00;
var expenses = 0.00;
var IncomeList = document.getElementById("incomeList");
var ExpenseList = document.getElementById("expenseList");
document.getElementById("submit").addEventListener("click", function() {
var DButton = document.createElement("button");
var t = document.createTextNode("Delete");
//document.body.appendChild(DButton);
DButton.appendChild(t);
// Converts the fake (non-existant)numbers into real (functionable) numbers
var aValue = parseFloat(Amount.value);
// if the operator is +, budget and income will increase by whatever you type in the value
if (Operator.value == "+") {
budget = budget += aValue;
income = income += aValue;
// The value that was typed along with description in will appear in the Income list in each line
IncomeList.innerHTML = IncomeList.innerHTML + Desc.value + ": " + aValue;
IncomeList.appendChild(DButton);
IncomeList.innerHTML = IncomeList.innerHTML + "<br>";
} else {
budget = budget -= aValue;
expenses = expenses -= aValue;
ExpenseList.innerHTML = ExpenseList.innerHTML + Desc.value + ": " + aValue;
ExpenseList.appendChild(DButton);
ExpenseList.innerHTML = ExpenseList.innerHTML + "<br>";
}
// Declaring statements to make it easier to input
document.getElementById("budget").innerText = budget;
document.getElementById("incomeTotal").innerText = income;
document.getElementById("expenseTotal").innerText = expenses;
});
<div id="wrapper">
<div id="top">
<p id="day">Available Budget in January 2018:</p>
<p id="budget">0.00</p>
<div id="income" class="highlight">
<h1>Income</h1>
<p id="incomeTotal">+0.00</p>
</div>
<div id="expenses" class="highlight">
<h1>Expenses</h1>
<p id="expenseTotal">-0.00</p>
</div>
</div>
<div id="controls">
<select id="operation">
<option>+</option>
<option>-</option>
</select>
<input type="text" placeholder="Add description" id="description" required/>
<input type="number" min="1" placeholder="Value" id="value" />
<button id="submit">✓</button>
</div>
<div id="content">
<div id="incomeList">
<p>INCOME</p>
</div>
<div id="expenseList">
<p>EXPENSES</p>
</div>
</div>
</div>
Hi, this is a budget tracker I made to practice JavaScript. So whenever users type a description and an amount and press submit, the list will show up along with a delete button that erases each line. How should I approach this method? Because the button is newly created by createElement, I do not know how to make this a handler...Thank you.
Append a row container instead of concatenating to the HTML string, and then you can attach a listener to the button that calls .remove() on the row.
It's often a good idea to avoid assigning to innerHTML when possible - it will corrupt all existing Javascript references to any elements inside. If you want to assign text alone, use textContent rather than innerHTML or createTextNode. (it's faster, safer, and more predictable)
var Operator = document.getElementById("operation");
var Desc = document.getElementById("description");
var Amount = document.getElementById("value");
var budget = 0.00;
var income = 0.00;
var expenses = 0.00;
var incomeList = document.getElementById("incomeList");
var expenseList = document.getElementById("expenseList");
document.getElementById("submit").addEventListener("click", function() {
const parent = Operator.value === "+" ? incomeList : expenseList;
const row = parent.appendChild(document.createElement('div'));
var DButton = row.appendChild(document.createElement("button"));
DButton.textContent = 'delete';
DButton.onclick = () => row.remove();
var aValue = parseFloat(Amount.value);
row.appendChild(document.createTextNode(Desc.value + ": " + aValue));
if (Operator.value == "+") {
budget = budget += aValue;
income = income += aValue;
} else {
budget = budget -= aValue;
expenses = expenses -= aValue;
}
// Declaring statements to make it easier to input
document.getElementById("budget").innerText = budget; document.getElementById("incomeTotal").innerText = income; document.getElementById("expenseTotal").innerText = expenses;
});
<div id="wrapper">
<div id="top">
<p id="day">Available Budget in January 2018:</p>
<p id="budget">0.00</p>
<div id="income" class="highlight">
<h1>Income</h1>
<p id="incomeTotal">+0.00</p>
</div>
<div id="expenses" class="highlight">
<h1>Expenses</h1>
<p id="expenseTotal">-0.00</p>
</div>
</div>
<div id="controls">
<select id="operation">
<option>+</option>
<option>-</option>
</select>
<input type="text" placeholder="Add description" id="description" required/>
<input type="number" min="1" placeholder="Value" id="value" />
<button id="submit">✓</button>
</div>
<div id="content">
<div id="incomeList">
<p>INCOME</p>
</div>
<div id="expenseList">
<p>EXPENSES</p>
</div>
</div>
</div>

Add an input value to a database value

I am working on a project where I have to add a database value to in input value.
<div>
<div class="price">680</div>
<div class="price">
<input type="number" name="name">
</div>
</div>
In above code 680 will come from the database. Here I want to add an input number to that 680. I am very new to jQuery.
My JavaScript code is
$(document).ready(function() {
var total = 0;
$("input").keyup(function(){
var priceList = $('.price');
$.each(priceList, function(i, price){
total += parseFloat($(price).text());
});
alert(total);
});
});
</script>
In this it outputs "NaN".
In this it outputs "NaN".
You get this message since you're trying to loop through div's and parsing the text of them, when it's empty. You need to loop over input's instead.
You could init the total with the database value then loop through the input's and add the parsed values to total in every iteration.
NOTE: Use input event instead when you track the user input since it's more efficient.
Multiple inputs:
$(document).ready(function() {
var db_val = parseFloat($('.price:first').text());
var total = 0;
$(".price input").on('input', function() {
var total = db_val;
$('.price input').each(function() {
total += parseFloat($(this).val()) || 0;
});
$(".total").text(total);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div class="price">680</div>
<div class="price">
<input type="number" name="name">
</div>
<div class="price">
<input type="number" name="name">
</div>
<div class="price">
<input type="number" name="name">
</div>
<div class="total">680</div>
</div>
Single input:
$(document).ready(function() {
var db_val = parseFloat($('.price:first').text());
var total = 0;
$(".price input").on('input', function() {
var total = db_val;
total += parseFloat($(this).val()) || 0;
$(".total").text(total);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div class="price">680</div>
<div class="price">
<input type="number" name="name">
</div>
<div class="total">680</div>
</div>
Here you go
var result = 0;
var price = +$('#price').text();
$('input[type="number"]').on('input', function() {
var val = +$(this).val();
result = parseInt(val + price);
$('#price').text(result)
console.log(result);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div class="price" id="price">680</div>
<div class="price">
<input type="number" name="name">
</div>

JavaScript - display keys and values of an array

I'm playing with a module object and trying to create a sort of blog (it's not going to be used in real life - just me learning stuff).
When a user fills a form and provides a tag, it checks whether the tag exists in an associative array, if not, it adds it with the value = 1. If the tag already exists, it adds +1 to the value. Now I want to display on a side how many entries for each tag there are, eg:
cooking(3)
sport(1)
It seems to partially work as when I add another tag, it displays in but keeps increasing the count of ALL the categories/tags:
cooking(1)
sport(1)
then
cooking(2)
sport(2)
...not just the one the user has just added.
var myArticles = (function () {
var s, articles;
return {
settings: {
articleList: "articles", // div with generated articles
articleClass: "article", // class of an article
articleIndex: 0,
sidebar: document.getElementById("sidebar"),
tagList: {},
// cats: Object.keys(this.settings.tagList)
},
init: function() {
// kick things off
s = this.settings;
articles = document.getElementById(this.settings.articleList);
this.createArticle();
},
createArticle: function() {
var div = document.createElement("div");
var getTag = document.getElementById("tag").value;
var getTitle = document.getElementById("title").value;
// Add classes
div.classList.add(this.settings.articleClass, getTag);
// Add title / content
var title = document.createElement("h2");
var textNode = document.createTextNode(getTitle);
title.appendChild(textNode);
div.appendChild(title);
// Add category
div.innerHTML += "Article" + this.settings.articleIndex;
articles.appendChild(div);
this.settings.articleIndex +=1;
this.updateCategories(getTag);
},
updateCategories: function(tag) {
// Create header
this.settings.sidebar.innerHTML = "<h3>Categories</h3>";
// Create keys and count them
if (tag in this.settings.tagList) {
this.settings.tagList[tag] += 1;
} else {
this.settings.tagList[tag] = 1;
}
var cats = Object.keys(this.settings.tagList);
// Create an unordered list, assign a class to it and append to div="sidebar"
var ul = document.createElement('ul');
ul.classList.add("ul-bare");
this.settings.sidebar.appendChild(ul);
// iterate over the array and append each element as li
for (var i=0; i<cats.length; i++){
var li=document.createElement('li');
ul.appendChild(li);
li.innerHTML=cats[i] + "(" + this.settings.tagList[tag] + ")";
}
}
};
}());
And HTML:
<body>
<div id="container">
<h1>My articles</h1>
<div id="genArticle" class="left">
<form id="addArt" method="post">
<div>
<label for="title">Title</label>
<input type="text" id="title" class="forma" placeholder="Title" required />
</div>
<div>
<label for="tag">Tag</label>
<input type="text" id="tag" class="forma" placeholder="Tag" required />
</div>
<div>
<label for="art">Article</label>
<textarea id="art" class="forma" required /></textarea>
</div>
<input type="button" onclick="myArticles.init()" value="Add Art">
<input type="reset" value="Reset Form">
<input type="range" size="2" name="satisfaction" min="1" max="5" value="3">
</form>
<div id="articles"></div>
</div> <!-- end of genArticle -->
<aside id="sidebar" class="right">
</aside>
</div> <!-- end of container -->
<script src="js/script.js"></script>
</body>
I think this line is wrong
li.innerHTML=cats[i] + "(" + this.settings.tagList[tag] + ")";
It is this.settings.tagList[cats[i]]
Not this.settings.tagList[tag]

How do I prevent jQuery result to show up in two different forms?

How do I get two separate results using jQuery in these forms? I enter information in the first form and the answer shows up in the second.
HTML:
<div class="span12">
<div class="span4">
<div class="row-fluid exercise1 one_rep_calc_container">
<form>
<div class="span4">Weight<input class="weight" type="number" name="weight" size="2" ></div>
<div class="span4">Reps<input class="reps" type="number" name="reps" size="2" ></div>
<div class="span4">OneRepMax<input class="one_rep_max" type="number" Name="oneRepMax" size="2" ></div>
</form>
</div>
</div>
<div class="span4">
<div class="row-fluid exercise1 one_rep_calc_container">
<form>
<div class="span4">Weight<input class="weight" type="number" name="weight" size="2" ></div>
<div class="span4">Reps<input class="reps" type="number" name="reps" size="2" ></div>
<div class="span4">OneRepMax<input class="one_rep_max" type="number" Name="oneRepMax" size="2" ></div>
</form>
</div>
</div>
</div>
The class oneRepMax is the solution form why the results of weight and reps.
jQuery:
$('.one_rep_calc_container .weight, .one_rep_calc_container .reps').change(function(){
var weight = parseInt($('.one_rep_calc_container .weight').val(), 10 );
var reps = parseInt($('.one_rep_calc_container .reps').val(), 10);
if(weight > 0 && reps > 0){
var oneRepMaxVal = ((reps*weight)/30) + weight;
$('.one_rep_calc_container .one_rep_max').val(oneRepMaxVal);
} else {
$('.one_rep_calc_container .one_rep_max').val('');
}
});
$('.one_rep_calc_container .calc_one_rep_button').click(function(){
var weight = parseInt($('.one_rep_calc_container .weight').val(), 10 );
var reps = parseInt($('.one_rep_calc_container .reps').val(), 10);
var oneRepMaxVal = ((reps*weight)/30) + weight;
$('.one_rep_calc_container .one_rep_max').val(oneRepMaxVal);
});
So how do I keep the results from the first form of oneRepMax separate from the second one?
Try this:
$('.one_rep_calc_container .weight, .one_rep_calc_container .reps').change(function(){
var parent = $(this).parents('.one_rep_calc_container');
var weight = parseInt(parent.find('.weight').val(), 10 );
var reps = parseInt(parent.find('.reps').val(), 10);
if(weight > 0 && reps > 0){
var oneRepMaxVal = ((reps*weight)/30) + weight;
parent.find('.one_rep_max').val(oneRepMaxVal);
}
else {
parent.find('.one_rep_max').val('');
}
});
$('.one_rep_calc_container .calc_one_rep_button').click(function(){
var parent = $(this).parents('.one_rep_calc_container');
var weight = parseInt(parent.find('.weight').val(), 10 );
var reps = parseInt(parent.find('.reps').val(), 10);
var oneRepMaxVal = ((reps*weight)/30) + weight;
parent.find('.one_rep_max').val(oneRepMaxVal);
});
The idea is to get the parent of the current element. That parent is the context for all your operations afterwards, with that way, you work only with the elements that are children of the current parent.
You should give your inputs ids so you can refer specifically to each.
<input id="weight1" class="weight" type="number" name="weight" size="2" >
Then you can use
$('#weight1').val()
to refer to specific ones.
Fundamentally, you should understand that the jquery selectors select and operate as many elements that match the criteria you specify. Both of the forms have the same identifiers and so the Jquery calls the functions on both of them. As others have mentioned you need to differentiate the two forms such that Jquery only operates on the one you want it to.

Categories

Resources