I have created an order form with multiple lines and columns
Product_id Qty price
Quantity and price are automatically filled out when Product is chosen in a drop down list.
At the end of the form, I have a field that sore the total amount <span id="total"></span>
I made the code below to calculate the total amount of the order but it doesn't work when qty and price are automatically filled. It does work if I type in qty or price
jQuery(function($) {
$(".qty, .price").change(function() {
var total = 0;
$(".qty").each(function() {
var self = $(this),
price = self.next(".price"),
subtotal = parseInt(self.val(), 10) * parseFloat(price.val(), 10);
total += (subtotal || 0);
});
$("#total").text(total);
});
});
You can use .trigger('change') or .change() while changing the textbox value from code:
$(".qty, .price").trigger('change');
or
$(".qty, .price").change();
For Example:
$(".qty").val('30').change();
I don't know if its correct but, have you tried using documnt.load()? you could put the code in a function that you call when page its loaded and when field value has changed.
You just need to separate you code into a new function such as:
var calculate = function() {
var total = 0;
$(".qty").each(function() {
var self = $(this),
price = self.next(".price"),
subtotal = parseInt(self.val(), 10) * parseFloat(price.val(), 10);
total += (subtotal || 0);
});
$("#total").text(total);
};
$(".qty, .price").change(calculate);
Then call it whenever you want.
Try calling a Function on page load and do it like this.
$( document ).ready(function() {
YourFunction();
YourFunction() function{
// insert your code
}
});
Then you can say
$(".qty, .price").change(function() {
YourFunction();
}
Related
I'm not sure how to explain this completely, but I hope this will make sense.
I have a function that I've made that calculates the remaining amount to spend to qualify for free delivery when the basket value total falls within certain thresholds.
The basket value is updated with AJAX every time a product is added to the basket.
The add to basket button appears in an AJAX generated modal.
I need my function to be called on every page refresh and also every time a product is added to the basket when the AJAX generated add to basket button is clicked. I'm trying to do all of this with the below, but it doesn't seem to work correctly. One of the problems is that the event fires multiple times when the add to basket button is clicked and another is that the basket total is updated after the event and so the total isn't calculated correctly.
Can anyone explain how I would tidy all off this up?
function totalBag() {
var standardDeliveryLow = 49.99;
var standardDeliveryHigh = 64.99;
var expressDeliveryLow = 65.00;
var expressDeliveryHigh = 99.99;
var bagValue = $('#basket-value').text();
var bagTotal = Number(bagValue.replace(/[^0-9\.-]+/g,""));
if (bagTotal >= standardDeliveryLow && bagTotal <= standardDeliveryHigh) {
var standardDifference = parseFloat(Math.round((standardDeliveryHigh - bagTotal) * 100) / 100).toFixed(2);
$('<div class="delivery-message"><p>£'+ standardDifference +' from standar delivery</p></div>').insertAfter('.breadcrumbs');
} else if (bagTotal >= expressDeliveryLow && bagTotal <= expressDeliveryHigh) {
var expressDifference = parseFloat(Math.round((expressDeliveryHigh - bagTotal) * 100) / 100).toFixed(2);
$('<div class="delivery-message"><p>£'+ expressDifference + ' from express delivery</p></div>').insertAfter('.breadcrumbs');
} else {
return false;
}
}
$(document).on('ajaxSuccess', function(e) {
$('[name="AddItemToBasket"]').on('click', function() {
$('body').bind('ajaxSuccess.custom', function() {
totalBag();
//alert('this works');
$(this).unbind('ajaxSuccess');
});
});
});
totalBag();
EDIT: Have fixed the issue where text was duplicating. Also have added comments for more understanding.
Had a check at the link you specified and tried the following modified code.
As per #ADyson, have removed the click event, which is fixing the multiple event firing.
Regarding your other problem, the total is updated after the event, yes the HTML is getting updated after the ajaxSuccess is triggered. Hence have used the ajaxSuccess event itself to get the basket amount and use it in totalBag fn.
It seems to be working. Kindly confirm:
//Adding empty div so that we can just update the value later
$(document).on('ready', function(){
$('<div class="delivery-message"></div>').insertAfter('.breadcrumbs');
})
function totalBag(bagTotal) {
var standardDeliveryLow = 49.99;
var standardDeliveryHigh = 64.99;
var expressDeliveryLow = 65.00;
var expressDeliveryHigh = 99.99;
//var bagValue = $('#basket-value').text();
//var bagTotal = Number(bagValue.replace(/[^0-9\.-]+/g,""));
//Using a variable to store the calculated amount with text
var innerHTML = "";
if (bagTotal >= standardDeliveryLow && bagTotal <= standardDeliveryHigh) {
var standardDifference = parseFloat(Math.round((standardDeliveryHigh - bagTotal) * 100) / 100).toFixed(2);
innerHTML= "<p>£"+ standardDifference +" from standar delivery</p>";
} else if (bagTotal >= expressDeliveryLow && bagTotal <= expressDeliveryHigh) {
var expressDifference = parseFloat(Math.round((expressDeliveryHigh - bagTotal) * 100) / 100).toFixed(2);
innerHTML= "<p>£"+ expressDifference +" from express delivery</p>";
} else {
return false;
}
//Updating the placeholder with new contents
$(".delivery-message").html(innerHTML);
}
//Gets triggered after every Ajax Success.
//e -> event object, xhr -> The Ajax object which has request and response details,
//settings -> The settings we used to trigger Ajax, including the request URL
$(document).on('ajaxSuccess', function(e, xhr, settings) {
//Checking if the request is of Adding Item to Basket
if(settings.url.indexOf("AddItemToBasket") !== -1){
//Getting the response and parsing it
var resp = xhr.responseText;
var respObj = JSON.parse(resp);
//Checking if response is success i.e., item added to cart successfully
if(respObj.success){
//Getting the updated Basket value and calling totalBag
var bagTotal = respObj.basket.subTotal;
totalBag(bagTotal);
}
}
});
totalBag(0);
I have this form where a user enters price and quantity, soon after the mouse leaves the 'Quantity' text box, I want the TotalPrice text box to be populated with result of Price * Quantity. The following is my jQuery code, however the TotalPrice text box does not get populated with the result. Hope someone can advise me on how to go about getting it right.
$("#quantity").mouseleave (function () {
var i = $("#price").val();
var k = $("#quantity").val();
var total = i*k;
$("#totalprice").val(total);
});
You need to use blur event handler of those two textboxes. Try this:
$(document).ready(function() {
$("#price").on("blur", calculate);
$("#quantity").on("blur", calculate);
//If you want to do the calculation when the page renders:
calculate();
});
function calculate(){
var i = $("#price").val();
var k = $("#quantity").val();
var total = i*k;
$("#totalprice").val(total);
}
As trincot mentioned in the comment below, you can merge the two events in one line since they call the same function:
$("#price, #quantity").on("blur", calculate);
I think you want this
jQuery(document).ready(function($) {
var price = $("#price");
var qty = $("#quantity");
var total = $("#totalprice");
/* CREATE VARIABLES ON DOCUMENT READY,
BECAUSE YOU WANT TO CACHE THE DOM SELECTION */
qty.on("blur", function(){
var i = price.val();
var k = qty.val();
total.val(i * k);
});
});
working fiddle ==> https://jsfiddle.net/tonysamperi/xqxm3900/
The problem with your code is that it is getting executed ONLY ONCE as soon as the ready function is called.
You need to attach a listner to the action element
$(document).ready(function() {
$("#quantity").mouseleave(function(){
var i = $("#price").val();
var k = $("#quantity").val();
var total = i*k;
$("#totalprice").val(total);
});
});
You can use various event listners such as onchange, onfocusout, blur, onkeyup depending on how and when you want the changes to happen. For more info on types of events and all for jquery only - https://api.jquery.com/category/events/
Planning to get the specific ID values from the selection on the HTML page (selection here means checked boxes). Here is my code for a button click event(button will fetch the row numbers or ids):
$("a", button).click(function () {
$('#groups').find('tr').each(function () {
var row = $(this);
if (row.find('input[type="checkbox"]').is(':checked')) {
console.log($(this));
}
});
});
This returns addtional information on rows + tr tag, however, I just want the ID part of it. Here is sample output I am getting out of above code:
[tr#row-12150.row.oddSelected, context: tr#row-12150.row.oddSelected]
[tr#row-12151.row.evenSelected, context: tr#row-12151.row.evenSelected]
This means I have selected 12150 and 12151 out of the #groups table. How do I just pull the row numbers 12150 and 12151 and not the entire detailed output and I want this to store in an array/(JS array) for multiple row numbers.
You have the row as per the .find('tr'), your should just be able to go:
console.log($(this).attr('id')); //this should show the id in your console.
so your code becomes:
$("a", button).click(function () {
$('#groups').find('tr').each(function () {
var row = $(this);
if (row.find('input[type="checkbox"]').is(':checked')) {
console.log($(this).attr('id'));
}
});
});
Then to just get the number you can use:
var number = $(this).attr(id).split('-')[1] //assuming it's always row-<<some number>>
putting it all together:
$("a", button).click(function () {
$('#groups').find('tr').each(function () {
var row = $(this);
if (row.find('input[type="checkbox"]').is(':checked')) {
var number = $(this).attr('id').split('-')[1] //assuming it's always row-<<some number>>;
console.log(number);
}
});
});
To store it in an array:
$("a", button).click(function () {
var checkedRows = []; //define empty array.
var count = 0; //keep a counter to use for the array.
$('#groups').find('tr').each(function () {
var row = $(this);
if (row.find('input[type="checkbox"]').is(':checked')) {
var number = $(this).attr('id').split('-')[1];
checkedRows[count] = number; //add the number to our array.
count++; //increase the count
}
});
});
Make sure your form and your button have id's first then try this instead:
$('#buttonId').click(function(){
$('#formId input:checked').each(i, e){
console.log($(e).attr('id'));
}
});
I have 2 select boxes with class starttime and endtime and if startime is chosen then values in end time will be disabled which are prior to the starttime. At the moment as all classnames are same if I change one starttime its effecting all end times, is there anyway I can prevent changing the end time of other tables row?
JavaScript
$("select[class='starttime']").on("change", function(){
$("select[class='endtime']").empty();
var startix = $("select[class='starttime'] option:selected").index();
$("select[class='starttime'] option").each(function(ix, el){
if (ix >= startix) {
$(this).clone().appendTo("select[class='endtime']");
}
});
});
JSFiddle: http://jsfiddle.net/rt194bxd/
UPDATE 1
If that's not possible because of no proper identifier then will setting up id to TR (table row) does help in anyway?
I did setup id for each TR in this JSFiddle http://jsfiddle.net/rt194bxd/1/
Rather than doing .appendTo("select[class='endtime']");, appendTo the specific select element; i.e. the select element coming after the one that's clicked.
We have to traverse the DOM and find it.
$("select[class='starttime']").on("change", function () {
var $this = $(this);
var nextSelect = $this.parent().next().children().first();
nextSelect.empty();
var startix = $("select[class='starttime'] option:selected").index();
$("select[class='starttime'] option").each(function (ix, el) {
if (ix >= startix) {
$(this).clone().appendTo(nextSelect);
}
});
});
Update:
Above code is a bit buggy. The correct way is shown below:
$("select[class='starttime']").on("change", function () {
var $this = $(this);
var nextSelect = $this.parent().next().children().first();
console.log(nextSelect[0].tagName);
//$("select[class='endtime']").empty();
nextSelect.empty();
var startix = $("option:selected", $this).index();
$("option", $this).each(function (ix, el) {
if (ix >= startix) {
$(this).clone().appendTo(nextSelect);
}
});
});
Fiddle: http://jsfiddle.net/rt194bxd/4/
$("select.starttime").on("change", function(){
// Access "<tr />" elem.
// This can be resolved better (this assumes there will be exactly
// one select.starttime per row. I'd recommend giving [unique] ID to
// each row (or select.endtime) and passing it to select.starttime
// (in extra attribute perhaps).
var parent = $('tr')[$("select.starttime").index(this)];
var $this = $(this);
// Clear select.endtime of same table row
$("select.endtime", parent).empty();
// Get selected option index of this <select />
var startix = $("option:selected", $this).index();
// Run through this <select /> options
$("option", $this).each(function(ix, el){
if (ix >= startix) {
$("select.endtime", parent).append($(this).clone());
}
});
});
Right now I'm using javascript to get the job done but i'm using onkeyup. This won't work for me because i'm using a button to populate the "var first". When a user pushes the button it populates the var first so there is no actual keyup/keydown.
<script>
window.onload = function () {
var first = document.getElementById('USERDEFINE1'),
//second = document.getElementById('ADDRESS2');
third = document.getElementById('PHONENIGHT');
fourth = document.getElementById('INTERNET');
fifth = document.getElementById('last_purchase');
sixth = document.getElementById('last_purchase_date');
first.onkeyup = function () { // or first.onchange
//second.value = '4444';
third.value = '111-111-1111';
fourth.value = 'NONE';
fifth.value = 'N/A';
sixth.value = 'N/A';
};
};
</script>
could i use something like:
if (document.getElementById(first.value) > 0
and if so how do i implement into my current javascript or should i rewrite it all together? Thanks in advance.
You will simply have to run the same population logic after pressing the button and after pressing a key in that input. You can also rely on other events like change, depending on how dynamic you want your interface to be.
Basically,
function populateInputs() {
//if we are in here, it means the value of first is > than 0
//at this point you can populate your other inputs
}
document.getElementById('your-button-id').addEventListener('click', function () {
first.value = 10; //init the value greater than 0
populateInputs(); //we know value is greater so populate
});
first.addEventListener('keyup', function () {
if (first.value > 0) {
populateInputs();
} else {
//first.value is not greater than 0
//reset input values to N/A or blank?
}
});