I am trying to change the text of the button clicked, using beforeSend and Complete in an ajax function, changing the text from Add to Cart > Adding... > Added to Cart, but the text is changed in all buttons, not sure how to target the button clicked.
HTML - the button text is wrapped in a space with data attributes
<span class="js-btn-cta" data-addbtn="{{ btn_txt }}" data-soldout="{{ btn_txt_soldout }}" data-offerbtn="{{ btn_txt_selling }}" data-adding-cart="{{ btn_adding }}" data-added-cart="{{ btn_added }}">
JS - I am then changing the text before the request is sent and once complete using the following methods;
//START AJAX API ADD TO CART FUNCTION
let miniCartContentsSelector = '.js-mini-cart-contents';
let addingCartBtn = $('.add-to-cart-button');
let addingCartText = $('.js-btn-cta');
let ajaxify = {
onAddToCart: function(event){
event.preventDefault();
$.ajax({
type: 'POST',
url: '/cart/add.js',
data: $(this).serialize(),
dataType: 'json',
beforeSend: function(e) {
//Update btn text on product and collection pages
dataAddingCart = addingCartText.attr('data-adding-cart'),
addingCartText.text(dataAddingCart);
},
complete: function(e) {
//Update btn text on product and collection pages
dataAddedCart = addingCartText.attr('data-added-cart'),
addingCartText.text(dataAddedCart);
},
success: function(){
ajaxify.onCartUpdated();
currencyPicker.setCurrencyText();
},
error: ajaxify.onError
});
shippingBar.update();
},
onCartUpdated: function() {
$.ajax({
type: 'GET',
url: '/cart',
context: document.body,
success: function(context){
let
$dataCartContents = $(context).find('.js-cart-page-contents'),
$dataCartContentsPrice = $(context).find('.js-total'),
dataCartHtml = $dataCartContents.html(),
dataCartItemCount = $dataCartContents.attr('data-cart-item-count'),
dataCartItemTotal = $dataCartContentsPrice.attr('data-cart-item-total'),
$miniCartContents = $(miniCartContentsSelector),
$cartItemCount = $('.js-cart-item-count'),
$closeIcon = $('.js-close-cart'),
$cartItemTotal = $('.js-cart-item-total');
$cartItemCount.text(dataCartItemCount);
$cartItemTotal.html('<span class="money">' + dataCartItemTotal + '</span>');
$miniCartContents.html(dataCartHtml);
//change currency in cart when changed
currencyPicker.setCurrencyText();
Currency.convertAll(shopCurrency, Currency.currentCurrency);
if (parseInt(dataCartItemCount) > 0){
ajaxify.openCart();
$('.js-minus').prop("disabled", true);
}
else {
ajaxify.closeCart();
}
//close the cart drawer when clicking on x in cart header
function closeClick(event){
$('body').removeClass('show-sidebar');
console.log('close icon btn clicked');
}
//end close the cart drawer when clicking on x in cart header
//call the closeClick function
$('.js-close-cart').click(closeClick);
//end call the closeClick function
}
});
//reset pdp qty value to 1 once add to cart has been clicked
$(".js-quantity-field-pdp").val("1");
shippingBar.update();
ajaxify.closeModal();
},
onError: function(XMLHttpRequest, textStatus){
let data = XMLHttpRequest.responseJSON;
alert(data.status + ' - ' + data.message + ': ' + data.description);
},
openCart: function(){
let isInCartPage = window.location.href.indexOf('/cart') === -1;
if(isInCartPage) {
$('body').addClass('show-sidebar');
}
},
closeCart: function(){
$('body').removeClass('show-sidebar');
},
closeModal: function(){
$('.modal').modal('hide');
$('.modal-backdrop').modal('hide');
},
onCartButtonClick: function(event){
event.preventDefault();
//If the body has a class of show-sidebar, return TRUE.
let isCartOpen = $('body').hasClass('show-sidebar');
let isInCart = window.location.href.indexOf('/cart') === -1;
if(!isInCart) {
if(!isCartOpen) {
ajaxify.openCart();
}
else {
ajaxify.closeCart();
}
}
},
init: function(){
$(document).on('submit', addToCartFormSelector, ajaxify.onAddToCart);
$(document).on('click', '.js-menu-toggle active', ajaxify.onCartButtonClick);
$(document).on('click', '#mini-cart .js-keep-shopping', ajaxify.onCartButtonClick);
}
};
//initiate the function
ajaxify.init();
The problem is it changes button text for other buttons not clicked.
Thanks
You get all button with class "js-btn-cta" and you change the text attribute to all button with this class. Not only the action button.
Inside onAddToCart, you have to get the clicked button.
onAddToCart: function(event){
var clickedButton = $(this);
event.preventDefault();
$.ajax({
type: 'POST',
url: '/cart/add.js',
data: $(this).serialize(),
dataType: 'json',
beforeSend: function(e) {
//Update btn text on product and collection pages
dataAddingCart = clickedButton.attr('data-adding-cart'),
clickedButton.text(dataAddingCart);
},
complete: function(e) {
//Update btn text on product and collection pages
dataAddedCart = clickedButton.attr('data-added-cart'),
clickedButton.text(dataAddedCart);
},
Related
I have written a code in Javascript in which I have attached an input type submit to a form. On form submit the listener gets called.
The problem is that on when I click the button once, one ajax call occurs. When I click it again two calls occur while only one call should occur on each click. Similarly on clicking 3 times 3 calls occur and so on...(the calls get increasing). If I refresh the page then the number gets reset. I have tried everything but I had no luck. If anyone found out what is wrong here it would be awesome. Thanks in advance.
javascript code:
$('input.create-discounts-quotations').click(function () {
var discount_quotation_type = $('input.quotation-discount-type').val();
if (discount_quotation_type == "value") {
var total = $('input.discount-input-quotation').val();
var discounted_price = product_price - total;
$('#final_discounted_amount').val(discounted_price);
$("table.product-response-table tr").each(function () {
var row = $(this).index() + 1;
var td = $(this).find('td.quotation-response-discounts');
$(td).each(function () {
$(this).html(total);
});
});
$("table.product-response-table tr").each(function () {
var row = $(this).index() + 1;
var td = $(this).find('td.product_final_price_discounted');
$(td).each(function () {
$(this).html(discounted_price);
});
});
var form1 = $('form#quotation_discount_update_form');
form1.on("submit", function (e) {
var form_data1 = form1.serialize();
$.ajax({
type: 'POST',
url: form1.attr('action'),
data: form_data1,
dataType: "json",
success: function (data) {
$('.quotation-discount-status-update').empty();
$('.quotation-discount-status-update').append('<div class="alert alert-success">Discount Added</div>');
}
});
e.preventDefault();
});
}
if (discount_quotation_type == "percentage") {
var total = $('input.discount-input-quotation').val();
var temp_first = product_price;
var temp1 = total / 100;
var temp2 = temp1 * product_price;
var discounted_price = product_price - temp2;
$('#final_discounted_amount').val(discounted_price);
$("table.product-response-table tr").each(function () {
var row = $(this).index() + 1;
var td = $(this).find('td.quotation-response-discounts');
$(td).each(function () {
$(this).html(total);
});
});
$("table.product-response-table tr").each(function () {
var row = $(this).index() + 1;
var td = $(this).find('td.product_final_price_discounted');
$(td).each(function () {
$(this).html(discounted_price);
});
});
var form1 = $('form#quotation_discount_update_form');
form1.on("submit", function (e) {
var form_data1 = form1.serialize();
$.ajax({
type: 'POST',
url: form1.attr('action'),
data: form_data1,
dataType: "json",
success: function (data) {
$('.quotation-discount-status-update').empty();
$('.quotation-discount-status-update').append('<div class="alert alert-success">Discount Added</div>');
}
});
e.preventDefault();
});
}
if (discount_quotation_type == "not_selected") {
$('.quotation-discount-status-update').empty();
$('.quotation-discount-status-update').append('<div class="alert alert-danger">Discount Method Not Selected</div>');
return false;
}
// return false;
});
That happen because every time you click your code will reattach the submit event so it will be duplicated in every click.
You should never attach the events inside other events, please put the submit event outside of the click event and the code should work, example :
var form1 = $('form#quotation_discount_update_form');
form1.on("submit", function (e) {
var form_data1 = form1.serialize();
$.ajax({
type: 'POST',
url: form1.attr('action'),
data: form_data1,
dataType: "json",
success: function (data) {
$('.quotation-discount-status-update').empty();
$('.quotation-discount-status-update').append('<div class="alert alert-success">Discount Added</div>');
}
});
e.preventDefault();
});
Else you have to remove the event handler every time using .off(), like :
form1.off("submit").on("submit", function (e) {
I'm making a script that when a user clicks a button a popup box displays with a text box of the tweet and a button for the user to retweet what's in the text box. In the script it's suppose to tell the user if it has retweeted successfully. The thing is that it tells the user it's successfully retweeted before the user has clicked the retweet button in the pop up box.
Seems as though just by clicking the button that activates the pop up box display is when the code activates a successful retweet message though nothing has been retweeted on the users end.
I'm not very familiar with javascript, my guess it's not the php code that's making the faulty logic but the javascript code. Here is what I have below.
(function($) {
$(document).ready(function() {
$.getScript("http://platform.twitter.com/widgets.js", function(){
twttr.events.bind('tweet', function(event) {
var targetUrl = event.target.src;
var query = getQueryParams(targetUrl);
click_callback(query.url);
});
});
});
})(jQuery);
function getQueryParams(qs) {
qs = qs.split("+").join(" ");
var params = {}, tokens,
re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])]
= decodeURIComponent(tokens[2]);
}
return params;
}
function click_callback(id){
var user = "<? echo $data->id;?>";
document.getElementById("Hint").style.display='block';
$("#Hint").html('Confirming Tweet...');
$.ajax({
type: "POST",
url: "plugins/rt/complete.php",
data: "id="+ id + "&user=" + user,
success: function(msg){
$("#Hint").html('Tweeted! Success!');
removeElement('boxes', id);
}
});
}
function removeElement(parentDiv, childDiv){
if (document.getElementById(childDiv)) {
var child = document.getElementById(childDiv);
var parent = document.getElementById(parentDiv);
parent.removeChild(child);
}
}
I think this is what's causing it within the code:
function click_callback(id){
var user = "<? echo $data->id;?>";
document.getElementById("Hint").style.display='block';
$("#Hint").html('Confirming Tweet...');
$.ajax({
type: "POST",
url: "plugins/rt/complete.php",
data: "id="+ id + "&user=" + user,
success: function(msg){
$("#Hint").html('Tweeted! Success!');
removeElement('boxes', id);
}
});
}
i made a function that sends data (ajax) to the database and depending on the response from the server i need to alert a message but it seems like whenvever i change the select option i get the alert message for each change(if i change the select four times when i click i get the alert four times ) , but if i remove my ajax function and replace it simply by an alert i get it once not repeating itself here is my JS
$('.select_ids').change(function () {
var id = $(this).val();
var form = $('#form_widget_ids_' + id);
var container = form.parent('.ewb_forms');
var box = container.parent('.edit_widget_box');
container.children('.selected').fadeOut(300, function () {
$(this).removeClass('selected');
form.fadeIn(300, function () {
$(this).addClass('selected');
});
});
Widget.updateSSOUrl(box);
$.ajax({
type: "POST",
url: window.location + "",
data: {'id': id}
}).done(function (msg) {
$(".red").on('click', function (evt) {
if ('done' == msg) {
evt.preventDefault();
alert('NOP');
}
})
});
});
the event that you are binding i think is wrong. For newly append items is better in your case to use
$(document).on('click', ".red", function (evt) {
})
And it must be moved outside the ajax success because now you are triggering it every time
----- Edited ---
If you want just to alert the output of the ajax you dont need the onClick event
$('.select_ids').change(function () {
var id = $(this).val();
var form = $('#form_widget_ids_' + id);
var container = form.parent('.ewb_forms');
var box = container.parent('.edit_widget_box');
container.children('.selected').fadeOut(300, function () {
$(this).removeClass('selected');
form.fadeIn(300, function () {
$(this).addClass('selected');
});
});
Widget.updateSSOUrl(box);
$.ajax({
type: "POST",
url: window.location + "",
data: {'id': id}
}).done(function (msg) {
if (msg === 'done') {
evt.preventDefault();
alert('NOP');
}
});
});
If you want to show the latest result on a button click you can store the msg on a global variable and on click of a div show that like
var globalMsg = "";
$('.select_ids').change(function () {
var id = $(this).val();
var form = $('#form_widget_ids_' + id);
var container = form.parent('.ewb_forms');
var box = container.parent('.edit_widget_box');
container.children('.selected').fadeOut(300, function () {
$(this).removeClass('selected');
form.fadeIn(300, function () {
$(this).addClass('selected');
});
});
Widget.updateSSOUrl(box);
$.ajax({
type: "POST",
url: window.location + "",
data: {'id': id}
}).done(function (msg) {
globalMsg = msg
});
});
$(".div").click(function() { alert(globalMSG); });
I have "load more" button, and if I click it fast enough it load the same content twice, and I want to prevent it.
This is how I call to the load more with ajax:
<script type="text/javascript">
function loadmore() {
var val = document.getElementById("result_no").value;
var userval = document.getElementById("user_id").value;
$.ajax({
type: 'post',
url: 'fetch.php',
data: {
getresult: val,
getuserid: userval
},
context: this,
success: function(response) {
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML + response;
document.getElementById("result_no").value = Number(val) + 10;
}
});
}
</script>
<div id="content">
<div id="result_para">
</div>
</div>
<input type="hidden" id="user_id" value="<?php echo $userid;?>">
<input type="hidden" id="result_no" value="15">
<input type="button" id="load" onclick="loadmore()" value="Load More Results">
You could set a loading variable to true at the start of loadmore, and set it back to false in the ajax callback. loading should be declared outside of loadmore though (see what a closure is).
var loading = false;
function loadmore()
{
if (loading) {
return ;
}
loading = true;
var val = document.getElementById("result_no").value;
var userval = document.getElementById("user_id").value;
$.ajax({
type: 'post',
url: 'fetch.php',
data: {
getresult:val,
getuserid:userval
},
context: this,
success: function (response) {
loading = false;
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
document.getElementById("result_no").value = Number(val)+10;
},
error: function () {
loading = false;
}
});
}
Instead of using that variable, you could also programmatically disable/enable the button, but that means that your button will flicker if the request is fast.
You can prevent from this by disable the button after first click, so change this lines:
success: function (response) {
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
document.getElementById("result_no").value = Number(val)+10;
}
With this lines:
success: function (response) {
document.getElementById("load").disabled = true;
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
document.getElementById("result_no").value = Number(val)+10;
document.getElementById("load").disabled = false;
}
you could disable the button when the "load more" button is clicked then then use the javascript function setTimeout to remove the disabled attribute from the button after a period of time. This would mean that the button would not be able to be clicked after the first click and even if the ajax request returned an error the button would still be able to be clicked.
$('#load').click(function {
// disable the button
$(this).prop('disabled', true);
// after three seconds enable the button again
var timeout = setTimeout(function() { $(this).prop('disabled', false); }, 3000);
});
I have a piece of code that does:
$('td.unique').live('click', function () {
//function logic here
});
This works fine on I click on the td of my table. All fine!
Now I would like to be able to have the same functionality programatically in certain cases without the user actually pressing click.
I have tried:
$(document).ready(function() {
$(".clearButton").click( function () {
var username = $(this).closest('tr').find('input[type="hidden"][name="uname"]').val();
var user_id = $(this).closest('tr').find('label').val();
var input = [];
input[0] = {action:'reset', id:user_id,user:username,};
$.ajax({
url: 'updateprofile.html',
data:{'user_options':JSON.stringify(input)},
type: 'POST',
dataType: 'json',
success: function (res) {
if (res.status >= 1) {
//all ok
console.log("ALL OK");
$(this).closest('tr').find('.unique').trigger('click');
$(this).closest('tr').find('td.unique').trigger('click');
$(this).closest('tr').find('td.unique').click();
}
else {
alert('failed');
}
}
});
This button is in the same row that the td.unique is
None of these work. Why? Am I doing it wrong? Is the function that I have bind in live not taken into account when I click this way?
You need to cache the $(this) inside the ajax function.
var $this = $(this);
the $(this) inside the ajax function will not refer to the element that is clicked
$(".clearButton").click(function () {
var $this = $(this);
var username = $this.closest('tr').find('input[type="hidden"][name="uname"]').val();
var user_id = $this.closest('tr').find('label').val();
var input = [];
input[0] = {
action: 'reset',
id: user_id,
user: username,
};
$.ajax({
url: 'updateprofile.html',
data: {
'user_options': JSON.stringify(input)
},
type: 'POST',
dataType: 'json',
success: function (res) {
if (res.status >= 1) {
console.log("ALL OK");
$this.closest('tr').find('.unique').trigger('click');
$this.closest('tr').find('td.unique').trigger('click');
$this.closest('tr').find('td.unique').click();
} else {
alert('failed');
}
}
});
});