1

I am trying to make an alert window fire when adding specific products to cart in WooCommerce. For this I am adding a click function to the add to cart button, that fires on ajaxComplete. However, the ajaxComplete seems to make it fire multiple times. How can I prevent this?

jQuery('#bvbutton').click(function() {
  jQuery( document ).ajaxComplete(function() {
    alert("testing!");
  });
});

EDIT: Per request here is a more thorough explanation: The ajax call is made from within WooCommerce and I would prefer not editing this. What I am trying to do is giving the buttons of the specific products a unique id, and making a click on a button with this id trigger an alert box.

The whole point is that items from within in a specific category, a, is supposed to give 10 % percent discount on products from category b. When adding a product from category a, the alert box is supposed to fire and inform about discount on category b. Hence I give these buttons a specific id, and would like to make a click event targeting these id's. When clicked, I need to await the ajax call that adds item to cart and then fire alert box.

Hope it makes sense now

user2806026
  • 787
  • 3
  • 10
  • 24

2 Answers2

2

$.ajaxComplete is global. This handler will be added to all AJAX requests as many times as is called. In your case each time #bvbutton is clicked a another handler instance is added globally.

Instead, add the handler once in the DOM ready event. Not on any specific click events.

$(function() {
  jQuery( document ).ajaxComplete(function() {
    alert("testing!");
  });
});
marekful
  • 14,986
  • 6
  • 37
  • 59
  • Thanks. However, I would like to attach it to the specific button. That way I can give the button for the specific items another ID and make them trigger the alert as needed. Any suggestions to this? – user2806026 Dec 17 '15 at 09:03
  • ie: i have a catalog with x items. y of the items has a button with id="bvbutton" and only those need to trigger the alert. – user2806026 Dec 17 '15 at 09:04
  • Since it is a global event, you cannot add it to a specific button. Add the desired behaviour to that specific AJAX request's callback which isn't global. Refer to @Andy's answer which describes good solution using custom events. – marekful Dec 17 '15 at 09:12
  • Thanks! I would like to edit only the frontpage template though - WooCommerce is handling the ajax call. – user2806026 Dec 17 '15 at 09:13
  • If you cannot / don't want to modify WC code, you can still add an event to the form or elements that describe the basket on the page. http://stackoverflow.com/questions/24279555/woocommerce-trigger-event-after-change-of-variation, https://wordpress.org/support/topic/woocommerce-customize-add-to-cart-variationjs – marekful Dec 17 '15 at 09:18
  • Wouldn't this fire when any product is added to cart? The whole point is that I only need it to fire when adding specific products to cart. The add to cart button of these products is given another id. – user2806026 Dec 17 '15 at 09:20
  • Be a bit more flexible on yourself! An event that fires on every product allows you to examine the added product and fire another event or make an alert if the product is of interest to you. – marekful Dec 17 '15 at 09:26
1

Personally I wouldn't do it this way as this will affect all AJAX operations that you do. I would be more inclined to use trigger to fire a custom event when that particular AJAX process is successful. That way you can be more precise as to when your alert goes off. Here's an example:

jQuery(document).on('product-added', function () {
  console.log('Product added');
});

jQuery('#bvbutton').click(function() {
  jQuery.ajax({
     url: endpoint,
     type: 'POST',
     ...
   }).success(function (data) {
     // process data
     jQuery(document).trigger('product-added');
   });
});
Andy
  • 61,948
  • 13
  • 68
  • 95
  • 2
    I have a feeling he wants to do something with WooCommerce ajax'.. not his ajax.. meaning, the ajax code is already there and will not be edited.. – Reigel Gallarde Dec 17 '15 at 09:11
  • Well, yeah. It makes sense. Problem is just that I would need to edit the ajax call in WooCommerce for this. I would really prefer only editing my frontend template :-) EDIT: Exactly as Reigel describes. – user2806026 Dec 17 '15 at 09:12
  • Point taken :) That said, does Woo not have an event that's fired when an AJAX call is complete? That seems a little remiss of them, particularly for an e-commerce application. – Andy Dec 17 '15 at 09:14
  • @user2806026, looks like you can use ["hooks"](http://wpcandy.com/teaches/how-to-use-wordpress-hooks/) to get this functionality. Some more [information here](https://docs.woothemes.com/document/introduction-to-hooks-actions-and-filters/). – Andy Dec 17 '15 at 09:23
  • well, I've looked into the source code, and here's what I found.. @Andy, you can expand your answer with this now.. ;) `$( document.body ).trigger( 'added_to_cart', [ fragments, cart_hash, $thisbutton ] );` – Reigel Gallarde Dec 17 '15 at 09:23
  • the very source... https://github.com/woothemes/woocommerce/blob/master/assets/js/frontend/add-to-cart.js – Reigel Gallarde Dec 17 '15 at 09:25
  • @Reigel, feel free to add your own answer with that info if you want. I'd prefer to keep mine as it is. – Andy Dec 17 '15 at 09:25
  • @Andy, your answer is already correct... I can't explain it even more.. oh well, he can still read comments :D – Reigel Gallarde Dec 17 '15 at 09:28
  • Okay. It seems to work, kinda.. The following triggers correctly with standard WooCommerce functionality: `jQuery(document.body).on("added_to_cart", function( data ) { alert("tester!"); });` However, on the single product pages, I am using a third party plugin for ajax, and this doesn't seem to trigger the same added_to_cart. Can I listen for something else here? Example page: http://tinyurl.com/obhqh7v – user2806026 Dec 17 '15 at 09:40
  • I am still struggling with this issue. Hoping one of you could find the time to checkout this new topic: http://stackoverflow.com/questions/34334797/woocommerce-added-to-cart-trigger – user2806026 Dec 17 '15 at 12:55