I have tried for so long now to auto calculate the sum of data attribute when adding/removing something to a shopping basket from and calculate the total of data attribute in pure JavaScript no Jquery without being able to fix it! I am pretty new to JavaScript...
Here is my code:
HTML:
//The shopping basket section
<div id="basket">Shopping Basket</div>
<ul class="cart" id="cart_id">
</ul>
<form>
<br>Total Price:
<input type="text" name="totalPrice" id="totalPrice" value="€ 0" disabled>
</form>
<div>
//The category selection section
<ul class="products" id="product_id">
<li class="cat" id="cat_id" name="data" data-title="iPad" data-price="299">iPad (€299)<img class="plusicon" src="plusicon.jpg" alt="plusicon"/></li>
<li class="cat" id="cat_id" name="data" data-title="iPad Air" data-price="399">Ipad Air (€399)<img class="plusicon" src="plusicon.jpg" alt="plusicon"/></li>
<li class="cat" id="cat_id" name="data" data-title="Sony Xperia Z2" data-price="399">Sony Xperia Z2 (€399)<img class="plusicon" src="plusicon.jpg" alt="plusicon"/></li>
<li class="cat" id="cat_id" name="data" data-title="Samsung Galaxy Tab 10,1" data-price="349">Samsung Galaxy Tab 10,1 (€349)<img class="plusicon" src="plusicon.jpg" alt="plusicon"/></li>
</ul>
JS :
function init(){
plus = [].slice.call(document.querySelectorAll(".plusicon"), 0);
for (var i = 0; i < plus.length; i++) {
plus[i].addEventListener("click", addToBasasket, false);
}
}
function addToBasket (e) {
e.stopPropagation();
var ele = info[plus.indexOf(this)];
var title = ele.getAttribute("data-title");
var price = parseInt(ele.getAttribute("data-price"));
var ul = document.getElementById("cart_id");
var li = document.createElement("li");
var remove = document.createElement("img");
remove.className = "removeicon";
remove.src = "removeicon.jpg";
remove.addEventListener("click", removeThingFromList, false);
li.appendChild(remove);
li.appendChild(document.createTextNode(title+" (\u20AC"+price+")"));
ul.appendChild(li);
//So when you press "plusicon" it adds to shopping basket and when you press "removeicon" it deletes from the basket!
//Here below is my problem, I have tried for so long but I cant get to work
//to show the total price when adding and removing li to basket!
var total = 0;
listItem = ele.getAttribute("data-price");
for (var i=0; i < listItem.length; i++)
{
total += parseInt(ele.getAttribute("data-price"));
}
document.querySelector("#totalPrice").value = total;
//I have tried so many different ways but can't get it to work the total of attribute("data-price")!
//This functions below works and removes the current li
function removeThingFromList(e){
this.parentNode.parentNode.removeChild(this.parentNode);
}
}
I hope someone can help! Thanks in advance!
You have to store the price in some attribute in new items (li) added to your basket :
li.appendChild(remove);
//Storing price in data-price attribute
li.setAttribute("data-price", price);
li.appendChild(document.createTextNode(title+" (\u20AC"+price+")"));
ul.appendChild(li);
And after that you can get this attribute and calculate the total :
var total = 0;
var listItem = document.getElementById("cart_id").getElementsByTagName("li");
for (var i=0; i < listItem.length; i++)
{
total += parseInt(listItem[i].getAttribute("data-price"));
}
<ul>
<li class="cart_item" data-prize="12.6" data-id="5">Hello €12.6</li>
<li class="cart_item" data-prize="4.25" data-id="8">World €4.25</li>
<li class="cart_item" data-prize="13.8" data-id="9">Foo €13.8</li>
<li class="cart_item" data-prize="6.3" data-id="12">Bar €6.3</li>
</ul>
<input type="button" value="TOTAL" onclick="calculateTotal();">
<div id="messages"></div>
<script>
function data(elm, key) {
for(var i in elm.attributes) {
if ( elm.attributes[i].name.substr(0, 5) === 'data-' ) { // checks if the 5 first letters of the attribute are 'data-'
// it's a data- attribute. Now let's see if it's the right one
if ( elm.attributes[i].name.substr(5) === key) { // checks if the letters, next to the 5 first letters, correspond with the key we need
return elm.attributes[i].value;
}
}
}
return '';
}
function calculateTotal() {
document.getElementById("messages").innerHTML = '';
var items = document.getElementsByClassName("cart_item");
var sum=0;
for (var i in items) {
var prize = Number( data(items[i], 'prize') ); // without the Number(), it's seen as text
sum += prize;
if(prize) { // else it also shows blank lines
document.getElementById("messages").innerHTML += prize + '<br>';
}
}
document.getElementById("messages").innerHTML += '+ -----<br>' + sum;
}
</script>
Related
Would I be able to add a remove button to replace the add button as of the image below and remove the values in that row from the array object that I have declared whenever I remove a certain row?
Image of the html (Partly)
Before Clone
After Clone
Desired Result
Html page
<div id="selections">
<div class="form-group row controls selection">
<label for="selection01" class="col-sm-2 col-form-label">Selection Pair</label>
<div class="col-sm-2">
<select class="form-control selection01" id="selection010" placeholder="Selection 01" onchange="addNewSelection()"></select>
</div>
<div class="col-sm-2">
<select class="form-control selection02" id="selection020" placeholder="Selection 02" onchange="addNewSelection()"></select>
</div>
<div class="col-sm-2">
<input type="number" min="0.00" max="10000.00" step="1.00" class="form-control" id="productQuantity0" placeholder="Quantity">
</div>
<div class="col-sm-2">
<input type="button" class="btn btn-success" id="addSelection" value="Add Selection" onclick="addNewSelectionPair()"></button>
</div>
</div>
</div>
Script
function addNewSelectionPair() {
// Get all selections by class
var selection = document.getElementsByClassName('selection');
// Get the last one
var lastSelection = selection[selection.length - 1];
// Clone it
var newSelection = lastSelection.cloneNode(true);
// Update the id values for the input
newSelection.children[1].children[0].id = 'selection01' + selection.length;
newSelection.children[2].childrne[0].id = 'selection02' + selection.length;
newSelection.children[3].children[0].id = 'productQuantity' + selection.length;
// Add it to selectionss
document.getElementById('selections').appendChild(newSelection)
}
function getValues() {
// Get all selections by class
var selections = document.getElementsByClassName('selection');
var values = [];
for(var i = 0; i < selections.length; i++) {
// Add the values into the array
values.push([
document.getElementById('selection01' + i).value,
document.getElementById('selection02' + i).value
document.getElementById('productQuantity' + i).value
]);
}
return values;
}
This script will duplicate the last row of inputs. It will also collect the inputs and store their values in a 3d array to process.
function addSection() {
//Get all sections by class
var sections = document.getElementsByClassName('section');
//Get the last one
var lastSection = sections[sections.length - 1];
//Clone it
var newSection = lastSection.cloneNode(true);
//Add it do sections
document.getElementById('sections').appendChild(newSection);
//Recalucate the Ids for the removal
//Ids all get shifted after adding or removing a section
calcRemovalIds();
}
function getValues() {
//Get all inputs by class
var sectionsOne = document.getElementsByClassName('section01');
var sectionsTwo = document.getElementsByClassName('section02');
var values = [];
//Loop the inputs
for(var i = 0; i < sectionsOne.length; i++) {
//Add the values to the array
values.push([
sectionsOne[i].value,
sectionsTwo[i].value
]);
}
return values;
}
function removeSection(id = undefined) {
//Get all sections by class
var sections = document.getElementsByClassName('section');
//If there is only one row left, just skip
if (sections.length == 1) return true;
//If not id was given, remove the last row
if (id == undefined) id = sections.length - 1;
//Get the last one
var lastSection = sections[id];
//Remove it
lastSection.parentNode.removeChild(lastSection);
//Recalucate the Ids for the removal
//Ids all get shifted after adding or removing a section
calcRemovalIds();
}
function calcRemovalIds() {
var btns = document.getElementsByClassName('button');
for (var i = 0; i < btns.length; i++) {
//Check if its the last button
if (i + 1 == btns.length) {
//Make it a addSection button
btns[i].innerHTML = '+';
btns[i].setAttribute('onclick', 'addSection()');
} else {
//Make is a removeSection button
btns[i].innerHTML = '-';
btns[i].setAttribute('onclick',
'removeSection(' + i +')'
);
}
}
}
<div>
<div>
<h2>Product</h2>
<input id="product" placeholder="Product" />
</div>
<div id="sections">
<div class="section">
<input class="section01" placeholder="Section One" />
<input class="section02" placeholder="Section Two" />
<button class="button" onclick="addSection()">+</button>
</div>
</div>
</div>
<button onclick="
document.getElementById('values').innerHTML = JSON.stringify(getValues());
">Get Values</button>
<div id="values"></div>
I am very new at JavaScript so a step by step answer would be much appreciated. Right now my code is set up so when you click the submit button it displays the total but instead I would like the total to be updated automatically by just checking the checkboxes and to not have a submit button at all.
function calcTotal()
{
var itemTotal = 0;
var items = document.getElementsByTagName("input");
for (var i = 0; i < 5; i++) {
if (items[i].checked){
itemTotal += parseInt(items[i].value);
}
}
document.getElementById("total").innerHTML = "Your order total is $" + itemTotal +".00";
}
var submitButton = document.getElementById("sButton");
submitButton.addEventListener("click", calcTotal);
Actually you need to bind Checkbox's event change, instead of Form submit button click. That whenever you change checkbox value by checking or unchecking it, It call the function calcTotal() to update the value.
Here is updated Javascript code:
function calcTotal()
{
var itemTotal = 0;
var items = document.getElementsByTagName("input");
for (var i = 0; i < 5; i++) {
if (items[i].checked){
itemTotal += parseInt(items[i].value);
}
}
document.getElementById("total").innerHTML = "Your order total is $" + itemTotal +".00";
}
var checkBoxItems = document.getElementsByTagName("input");
checkBoxItems.addEventListener("change", calcTotal);
Hope it will help you.
Just add a change event to every checkbox. When you toggle the checked state, recalculate the total by grabbing the :checked checkboxes.
Array.from(document.querySelectorAll('input[type="checkbox"]')).forEach(chk => {
chk.addEventListener('change', recalculateTotal);
});
function recalculateTotal() {
let total = Array.from(document.querySelectorAll(':checked')).reduce((sum, chk) => {
return sum + parseInt(chk.value, 10);
}, 0);
document.getElementById('total').innerHTML = '$' + total.toFixed(2);
}
label { display: inline-block; margin-right: 1em; }
div { margin-top: 1em; }
<label>$1 <input type="checkbox" value="1" /></label>
<label>$10 <input type="checkbox" value="10" /></label>
<label>$100 <input type="checkbox" value="100" /></label>
<div>Your order total is: <span id="total">$0.00</span></div>
The key is listening to the input event on the input elements instead of the click event on the button element.
Additional notes, when possible:
Use single quotes in JS, double quotes in HTML
Use let or const instead of var
Don't reinvent .reduce when you need to reduce an array of values into a single value (e.g. compute a sum).
Use template strings (e.g. `y: ${y}`) instead of concatenating strings (e.g. "y: " + y).
let inputs = [...document.querySelectorAll("input")];
let calcTotal = () => {
let sum = inputs.reduce((sum, input) => sum + (input.checked ? parseInt(input.value) : 0), 0);
document.querySelector("#total").textContent = `Your order total is $${sum}.00`;
};
inputs.forEach(input => input.addEventListener('input', calcTotal));
<label><input type="checkbox" value=30>$30 hamburger</label>
<label><input type="checkbox" value=45>$45 french fries</label>
<label><input type="checkbox" value=1>$1 cola</label>
<label><input type="checkbox" value=60>$60 parking</label>
<label><input type="checkbox" value=20>$20 cookie</label>
<label><input type="checkbox" value=290>$290 large cookie</label>
<div id="total"></div>
I'm beginer in js, please help me.
I have two functions. First function sum all checked input ticket and view sum price, secondary function check discount code and takes into account the new price.
The problem is when I add a discount code and then will choose a ticket. Then it does not calculate the value.
https://jsfiddle.net/wznvfkm3/
$('.participantEventTicket').on('change', function() {
var totalPrice = 0.00;
$('.participantEventTicket:checked').each(function() {
totalPrice += parseFloat($(this).data('price'), 10);
});
$('.participantEventTicketSum').html(totalPrice.toFixed(2));
$('.participantEventTicketDiscountValueTotal').html(totalPrice);
});
$('.participantEventTicketDiscount').on('change', function() {
var code = ($(this).val());
var valueTotal = document.getElementById('participantEventTicketSum').innerHTML;
var value = 0;
var liste = [];
liste[0] = ['ABB'], -5]; liste[1] = ['BBC'], -10];
for (var i = 0, len = liste.length; i < len; i++) {
if (liste[i][0] === code) {
var value = liste[i][1];
}
}
var valueTotalS = parseInt(valueTotal) + parseFloat(value);
$('#participantEventTicketDiscountValue').html(value.toFixed(2));
$('#participantEventTicketDiscountValueTotal').html(valueTotalS);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
ticket 1
<input type="checkbox" name="participantEventTicket[]" value="5" class="participantEventTicket" />
<br/>ticket 2
<input type="checkbox" name="participantEventTicket[]" value="10" class="participantEventTicket" />
<br/>Sume tickets: <span class="participantEventTicketSum" id="participantEventTicketSum">0.00</span>
<br/>Discount coupon
<input type="text" id="participantEventTicketDiscount" class="participantEventTicketDiscount">
<br/>Discount value <span id="participantEventTicketDiscountValue" class="participantEventTicketDiscountValue">0.00</span>
<br/>Discount value sum <span id="participantEventTicketDiscountValueTotal" class="participantEventTicketDiscountValueTotal">0.00</span>
</form>
Slawotu,
Please check this fiddle
You had couple errors:
$('.participantEventTicket:checked').each(function () { totalPrice += parseFloat($(this).val(), 10);});
// you supposed to take $(this).val()
You didn't put calculation of total Price when you entered discount and changed you ticket:
$('.participantEventTicketDiscountValueTotal').html(totalPrice + value);
Forgot but brackets:
liste[0] = [['ABB'], -5];
liste[1] = [['BBC'], -10];
You compared 2 different objects using === instead use ==
if (liste[i][0] == code)
Declare val on top of the file, don't declare inside if statement.
var value = 0;
I have a little product search code that I've been working on for a while. It works great, although a bit backwards.
The more keywords I type in, ideally, the less products will show up (because it narrows down the results). But as is stands, the more keywords I type in my search system, the MORE products are displayed, because it looks for any product with any of the keywords.
I want to change the script so that it only shows results if they include ALL the searched for keywords, not ANY of them...
Sorry for the long-winded explanation.
Here's the meat and potatoes (jsfiddle):
http://jsfiddle.net/yk0Lhneg/
HTML:
<input type="text" id="edit_search" onkeyup="find_my_div();">
<input type="button" onClick="find_my_div();" value="Find">
<div id="product_0" class="name" style="display:none">Mac
<br/>Apple
<br/>
<br/>
</div>
<div id="product_1" class="name" style="display:none">PC
<br/>Windows
<br/>
<br/>
</div>
<div id="product_2" class="name" style="display:none">Hybrid
<br/>Mac PC Apple Windows
<br/>
<br/>
</div>
JAVASCRIPT:
function gid(a_id) {
return document.getElementById(a_id);
}
function close_all() {
for (i = 0; i < 999; i++) {
var o = gid("product_" + i);
if (o) {
o.style.display = "none";
}
}
}
function find_my_div() {
close_all();
var o_edit = gid("edit_search");
var str_needle = edit_search.value;
str_needle = str_needle.toUpperCase();
var searchStrings = str_needle.split(/\W/);
for (var i = 0, len = searchStrings.length; i < len; i++) {
var currentSearch = searchStrings[i].toUpperCase();
if (currentSearch !== "") {
nameDivs = document.getElementsByClassName("name");
for (var j = 0, divsLen = nameDivs.length; j < divsLen; j++) {
if (nameDivs[j].textContent.toUpperCase().indexOf(currentSearch) !== -1) {
nameDivs[j].style.display = "block";
}
}
}
}
}
So, when you search "mac pc" the only result that should be displayed is the hybrid, because it has both of those keywords. Not all 3 products.
Thank you in advance!
I changed a little bit your code to adjust it better to my solution. I hope you don't mind. You loop first over the terms, and then through the list of products, I do it the other way around.
How this solution works:
Traverse the list of products, for each product:
Create a counter and set it to 0.
Traverse the list of search terms, for each.
If the word is found in the product's name, add 1 to the counter.
If the counter has the same value as the list length, display the product (matched all words)
function gid(a_id) {
return document.getElementById(a_id);
}
function close_all() {
for (i = 0; i < 999; i++) {
var o = gid("product_" + i);
if (o) {
o.style.display = "none";
}
}
}
function find_my_div() {
close_all();
var o_edit = gid("edit_search");
var str_needle = edit_search.value;
str_needle = str_needle.toUpperCase();
var searchStrings = str_needle.split(/\W/);
// I moved this loop outside
var nameDivs = document.getElementsByClassName("name");
for (var j = 0, divsLen = nameDivs.length; j < divsLen; j++) {
// set a counter to zero
var num = 0;
// I moved this loop inside
for (var i = 0, len = searchStrings.length; i < len; i++) {
var currentSearch = searchStrings[i].toUpperCase();
// only run the search if the text input is not empty (to avoid a blank)
if (str_needle !== "") {
// if the term is found, add 1 to the counter
if (nameDivs[j].textContent.toUpperCase().indexOf(currentSearch) !== -1) {
num++;
}
// display only if all the terms where found
if (num == searchStrings.length) {
nameDivs[j].style.display = "block";
}
}
}
}
}
<input type="text" id="edit_search" onkeyup="find_my_div();">
<input type="button" onClick="find_my_div();" value="Find">
<div id="product_0" class="name" style="display:none">Mac
<br/>Apple
<br/>
<br/>
</div>
<div id="product_1" class="name" style="display:none">PC
<br/>Windows
<br/>
<br/>
</div>
<div id="product_2" class="name" style="display:none">Hybrid
<br/>Mac PC Apple Windows
<br/>
<br/>
</div>
You can also see it on this version of your JSFiddle: http://jsfiddle.net/yk0Lhneg/1/
This function replicates the user experience of a Select/MultiSelect dropdown element - displaying the values of checkboxes checked in a container (adds/removes them when they're checked/unchecked), and if more than 3 items have been checked it displays the # selected instead of the values selected.
It's a combination of 2 functions and they're not playing well together when items are unchecked (i.e. it's removing the values but not the commas, doesn't work correctly when more than 3 items have been selected, etc.)
I think it would be much better if I used an array to store the values, adding/removing values from the array when items are checked/unchecked, and I know how do to in PHP but not in Javascript. This code should create the array, but I can't figure out how to integrate it into my code.
$('input:checkbox[name="color[]"]:checked').each(function () {
selectedColors.push($(this).val());
});
Existing Code:
JS
$(".dropdown_container ul li").click(function () {
var text = $(this.children[0]).find("input").val();
var text_edited = text.replace(/_/g, " ");
var currentHtml = $(".dropdown_box span").html();
var positionLocation = currentHtml.indexOf(text_edited);
var numberChecked = $('input[name="color[]"]:checked').length;
if (positionLocation < 1) {
if (numberChecked <= 3) {
$(".dropdown_box span").html(currentHtml.replace('Colors', ''));
$(".dropdown_box span").append(', ' + text_edited);
} else {
$(".dropdown_box span").html(currentHtml.replace(currentHtml, numberChecked + " Selected"));
}
} else {
(currentHtmlRevised = currentHtml.replace(text_edited, ""));
$(".dropdown_box span").html(currentHtmlRevised.replace(currentHtml));
}
});
HTML
<div class="dropdown_box"><span>Colors</span></div>
<div class="dropdown_container">
<ul id="select_colors">
<li>
<label><a href="#"><div style="background-color: #ff8c00" class="color" onclick="toggle_colorbox_alt(this);"><div class=CheckMark>✓</div>
<input type="checkbox" name="color[]" value="Black" class="cbx"/>
</div>Black</a></label>
</li>
<!-- More List Items --!>
</ul>
</div>
Easiest to just replace the entire content each time. Also use the change event instead of the click event.
$(".dropdown_container input").change(function () {
var checked = $(".dropdown_container input:checked");
var span = $(".dropdown_box span");
if (checked.length > 3) {
span.html("" + checked.length + " selected");
}
else {
span.html(checked.map(function () { return $(this).val().replace("_"," "); }).get().join(", "));
}
});
Example: http://jsfiddle.net/bman654/FCVjj/
try this:
$('.cbx').change(function(){
var cbx = $('.cbx:checked');
var str = '';
if (cbx.length<=3 && cbx.length!=0){
for (var i=0;i<cbx.length;i++){
if (i>0) str += ', ';
str += cbx[i].value;
}
} else if (cbx.length==0){
str = 'Colors';
} else {
str = cbx.length;
}
$('.dropdown_box span').html(str);
});