Woocommerce mini cart widget Quantity changes - php

I want to change quantity of products in mini cart widget after add into the cart. I get solution from another post of stackoverflow but for some reason its works slow to update the quantity in cart widget.. Its my first post on stackoverflow not have much idea how it works.
URL of page where have issue
Custom code in 3 parts
Part 1 of 3
//Plus Button for increase quantity
<a href="/tbones2/?wc-ajax=get_refreshed_fragments&add-to-cart=<?php echo $cart_item['product_id']; ?>" rel="nofollow" data-product_id="<?php echo $cart_item['product_id'] ?>" data=quantity="1" data-product_sku="<?php echo $cart_item['product_id']; ?>" class="wdiget_qty_btn add_to_cart_button ajax_add_to_cart"><i class="icon-plus-squared"></i>
</a>
Part 2 of 3
I created the template for handling the setquantity triggers.
<?php
/**
* Template Name: Request template for Set Quantity
* This page updates mini cart quantity for a product based on the post value
*/
//I dont think this line is needed
global $woo_options;
?>
<html>
<head>
<?php wp_head(); ?>
</head>
<body>
<?php
//the cart key stores information about cart
$cartKeySanitized = filter_var($_POST['cart_item_key'], FILTER_SANITIZE_STRING);
//the new qty you want for the product in cart
$cartQtySanitized = filter_var($_POST['cart_item_qty'], FILTER_SANITIZE_STRING);
//update the quantity
global $woocommerce;
ob_start();
$woocommerce->cart->set_quantity($cartKeySanitized,$cartQtySanitized);
ob_get_clean();
wp_footer(); ?>
<?php woo_foot(); ?>
</body>
</html>
Part 3 of 3
Now in this part there is Ajax function for update the quantity in cart widget.
<script type="text/javascript">
function updateQty(key, qty) {
url = 'https://buzzpreview.com/tbones2/updatecart/';
data = "cart_item_key=" + key + "&cart_item_qty=" + qty;
jQuery.post(url, data).done(function (data) {
//function updateCartFragment
updateCartFragment();
});
}
function updateCartFragment() {
$('#mini-loader').html('loading...');
$fragment_refresh = {
url: woocommerce_params.ajax_url,
type: 'POST',
data: {action: 'woocommerce_get_refreshed_fragments'},
success: function (data) {
if (data && data.fragments) {
jQuery.each(data.fragments, function (key, value) {
jQuery(key).replaceWith(value);
});
if ($supports_html5_storage) {
sessionStorage.setItem("wc_fragments", JSON.stringify(
data.fragments));
sessionStorage.setItem("wc_cart_hash", data.cart_hash);
}
jQuery('body').trigger('wc_fragments_refreshed');
}
}
};
//Always perform fragment refresh
jQuery.ajax($fragment_refresh);
}
</script>

Please add this below method to your JS code
function supports_html5_storage() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
}
and change if ($supports_html5_storage) to if (supports_html5_storage) , that's it.

Related

Additional Woocommerce product Add To Cart button that redirect to checkout

I need the customer to be able to choose between add to cart and continue to shop and add to cart and get re-directed to the checkout. In other words, I'm adding a extra button to the product page.
Being new to WooCommerce, I'm struggling getting the qty input to function. It works fine if buying just one, but not when adding more than one (qty).
Also, I'm failing to understand how to add support for variable products, but that might be a separate question? (sorry if so).
Here's the code I'm using:
add_action( 'woocommerce_after_add_to_cart_button', 'add_content_after_addtocart' );
function add_content_after_addtocart() {
$current_product_id = get_the_ID();
$product = wc_get_product( $current_product_id );
$checkout_url = WC()->cart->get_checkout_url();
if( $product->is_type( 'simple' )) { ?>
<script>
jQuery(function($) {
$(".custom-checkout-btn").on("click", function() {
$(this).attr("href", function() {
return this.href + '&quantity=' + $('input.qty').val();
});
});
});
</script>
<?php
echo 'Buy & Checkout';
}
}
Any input on where I'm going wrong? All the help I can get is appreciated.
There are some mistakes in your code… Try the following:
add_action( 'woocommerce_after_add_to_cart_button', 'add_custom_addtocart_and_checkout' );
function add_custom_addtocart_and_checkout() {
global $product;
$addtocart_url = wc_get_checkout_url().'?add-to-cart='.$product->get_id();
$button_class = 'single_add_to_cart_button button alt custom-checkout-btn';
$button_text = __("Buy & Checkout", "woocommerce");
if( $product->is_type( 'simple' )) :
?>
<script>
jQuery(function($) {
var url = '<?php echo $addtocart_url; ?>',
qty = 'input.qty',
button = 'a.custom-checkout-btn';
// On input/change quantity event
$(qty).on('input change', function() {
$(button).attr('href', url + '&quantity=' + $(this).val() );
});
});
</script>
<?php
echo ''.$button_text.'';
endif;
}
Code goes in function.php file of your active child theme (or active theme). It should works.

Add pop up and a custom message based on country in Woocommerce checkout

I am using the below code which works well to add a message to the woocommerce checkout when customers choose a country. But i also want to add a pop up using this shortcode
echo do_shortcode('[sg_popup id=3839] ');
But when i add it below the text message the pop up always shows, i.e. if i add the following
`echo '<div class="shipping-notice woocommerce-info" style="display:none">Please allow 5-10 business days for delivery after order processing.'; echo do_shortcode('[sg_popup id=3839] '); echo '</div>'
I imagine its because it is only hiding the code so it is actually running the shortcode? But what other options do I have?
Any help is appreciated.
add_action( 'woocommerce_before_checkout_billing_form', 'display_shipping_notice' );
function display_shipping_notice() {
echo '<div class="shipping-notice woocommerce-info" style="display:none">Please allow 5-10 business days for delivery after order processing.</div>';
}
add_action( 'woocommerce_after_checkout_form', 'show_hide_shipping_notice' );
function show_hide_shipping_notice(){
?>
<script>
jQuery(document).ready(function($){
// Set the country code (That will display the message)
var countryCode = 'FR';
$('select#billing_country').change(function(){
selectedCountry = $('select#billing_country').val();
if( selectedCountry == countryCode ){
$('.shipping-notice').hide();
}
else {
$('.shipping-notice').show();
}
});
});
</script>
<?php
}
The following code will show or hide a custom shipping notice depending on the chosen country (the code handle both billing and shipping country)…
To replace your shortcode, you can use instead a popup like using Sweet Alert 2 (a lightbox):
// Displaying a custom shipping notice
add_action( 'woocommerce_checkout_before_customer_details', 'checkout_country_shipping_notice' );
function checkout_country_shipping_notice() {
?>
<style>.shipping-notice.hidden{display:none;}</style>
<?php
$country = WC()->customer->get_shipping_country();
$country = empty($country) ? WC()->customer->get_billing_country() : $country;
$text = __("Please allow 5-10 business days for delivery after order processing.", "woocommerce" );
$class = 'woocommerce-info shipping-notice';
// Hidden if France or empty
if( empty($country) || $country == 'FR' )
$class .= ' hidden';
echo '<div class="'.$class.'">'.$text.'</div>';
}
// The jQuery code to show / hide the custom shipping notice
add_action( 'wp_footer', 'checkout_country_script' );
function checkout_country_script() {
// Only checkout page
if( is_checkout() && ! is_wc_endpoint_url() ):
?>
<script src="https://unpkg.com/sweetalert2#8.8.1/dist/sweetalert2.all.min.js"></script>
<script src="https://unpkg.com/promise-polyfill#8.1.0/dist/polyfill.min.js"></script>
<script type="text/javascript">
jQuery(function($){
var fc = 'form.checkout', sn = '.shipping-notice',
bc = 'select#billing_country', sc = 'select#shipping_country',
sda = 'input#ship-to-different-address-checkbox';
// Function that show hide the shipping notice
function showHideNotice(t){
if( $(t).val() == 'FR' || $(t).val() == undefined ){
$(sn).hide( function(){
$(this).removeClass('hidden');
});
} else {
$(sn).hide( 'fast', function(){
if( ! $(this).hasClass('hidden') )
$(this).addClass('hidden');
$(sn).show();
// Add a Sweet alert 2 popup
swal({
title: '<?php _e("Custom popup title", "woocommerce"); ?>',
text: '<?php _e("This is the text for my popup", "woocommerce"); ?>',
type: 'info' // can be: warning, error, success, info or question
});
});
}
}
// Billing and shipping country change
$(bc+','+sc).change(function(){
if($(sda).prop('checked'))
showHideNotice(sc);
else
showHideNotice(bc);
});
});
</script>
<?php
endif;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

JS alert on ajax add to cart for specific product category count in Woocommerce

In Woocommerce I'm trying to display a JavaScript "Sweet alert" when a specific count of products in the cart from a specific category is reached. Items are added to the cart via AJAX which is why I want to use a JavaScript alert (Sweet alert).
e.g. IF cart contains 5 products from category "Bags" - Display alert.
I have researched and found the following helpful answers and used them to build out my code. However, I am struggling with applying the rule to only count products from a specific category.
Display a sweet alert on AJAX add to cart for a specific Woocommerce cart product count
Counting cart-items of specific product category
At the moment, the code below successfully triggers, but only based on the number of products in the cart. It ignores the product category rule:
Loop Through cart items and set the product category counter:
// Wordpress Ajax: Get different cart items count
add_action( 'wp_ajax_nopriv_checking_items', 'checking_items' );
add_action( 'wp_ajax_checking_items', 'checking_items' );
function checking_items() {
global $woocommerce, $product;
$i=0;
// Set minimum product cart total
$total_bags = 0;
$total_shoes = 0;
if( isset($_POST['added'])){
// Loop through cart for product category
foreach ( $woocommerce->cart->cart_contents as $product ) :
if ( has_term( 'bags', 'product_cat', $product['22'] ) ) {
$total_bags += $product['quantity'];
} else {
$total_shoes += $product['quantity'];
}
endforeach;
}
die(); // To avoid server error 500
}
Using jQuery, if count of category met, display JavaScript alert.
// The Jquery script
add_action( 'wp_footer', 'item_check' );
function item_check() {
?>
<script src="https://unpkg.com/sweetalert2#7.20.1/dist/sweetalert2.all.js"></script>
<script type="text/javascript">
jQuery( function($){
// The Ajax function
$(document.body).on('added_to_cart', function() {
console.log('event');
$.ajax({
type: 'POST',
url: wc_add_to_cart_params.ajax_url,
data: {
'action': 'checking_cart_items',
'added' : 'yes'
},
//ONLY DISPLAY ALERT IF TOTAL ITEMS IS FROM CATEGORY BAGS
success: function ($total_bags) {
if($total_bags == 5 ){
//DISPLAY JAVASCRIPT ALERT
const toast = swal.mixin({
toast: true,
showConfirmButton: false,
timer: 3000
});
toast({
type: 'success',
title: '5 Items Added!'
})
}
}
});
});
});
</script>
<?php
}
There is some errors and mistakes in your code. Try this revisited code instead:
// Wordpress Ajax: Get different cart items count
add_action( 'wp_ajax_nopriv_checking_items', 'checking_cart_items' );
add_action( 'wp_ajax_checking_items', 'checking_cart_items' );
function checking_cart_items() {
if( isset($_POST['id']) && $_POST['id'] > 0 ){
// Initialising variables
$count = 0;
$product_id = $_POST['id'];
$category = 'bags';
$category = 't-shirts';
// Loop through cart for product category
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( has_term( $category, 'product_cat', $cart_item['product_id'] ) ) {
$count += $cart_item['quantity'];
}
}
// Only if the added item belongs to the defined product category
if( has_term( $category, 'product_cat', $_POST['id'] ) )
echo $count; // Returned value to jQuery
}
die(); // To avoid server error 500
}
// The Jquery script
add_action( 'wp_footer', 'items_check' );
function items_check() {
if(is_checkout()) return; // Except on checkout page
?>
<script src="https://unpkg.com/sweetalert2#7.20.1/dist/sweetalert2.all.js"></script>
<script type="text/javascript">
jQuery( function($){
// wc_add_to_cart_params is required to continue
if ( typeof wc_add_to_cart_params === 'undefined' )
return false;
$(document.body).on( 'added_to_cart', function( event, fragments, cart_hash, $button ) {
// The Ajax request
$.ajax({
type: 'POST',
url: wc_add_to_cart_params.ajax_url,
data: {
'action': 'checking_items',
'id' : $button.data( 'product_id' ) // Send the product ID
},
//ONLY DISPLAY ALERT IF TOTAL ITEMS IS FROM CATEGORY BAGS
success: function (response) {
console.log('response: '+response); // Testing: to be removed
if(response == 5 ){
//DISPLAY JAVASCRIPT ALERT
const toast = swal.mixin({
toast: true,
showConfirmButton: false,
timer: 3000
});
toast({
type: 'success',
title: '5 Items Added!'
})
}
}
});
});
});
</script>
<?php
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
If you look on your browser inspector javascript console, you will see that ajax is working in the right way, returning each time the items count for that specific product category:

Replace "add to cart" with custom quantity input fields in WooCommerce

I am using WooCommerce with Storefront theme to build an eCommerce website that will be used on smartphones mostly. So I am trying to reduce the number of clicks and buttons to make it as simple as possible.
I would like to replace "add to cart" button with a quantity selector :
I found a way to add a quantity selector next to "add to cart" button (e.g. with plugin WooCommerce Advanced Product Quantities) but I would like to get rid of "add to cart" button.
So, when a customer click on "+", it should add 1 element to the cart and the number should display the quantity in the cart.
Also (no idea if this is possible...), I'd like an animation to notify the customer that the product was well added to the cart. For instance, show a "+1" for a few seconds near the cart icon,
here you go it's going to be long one :
First Let's Remove the Add To Cart Button:
// Remove Add To cart Button
remove_action('woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10);
Now Lets Create our Input and add it to shop page
// Add our Quanity Input
add_action('woocommerce_after_shop_loop_item', 'QTY');
function QTY()
{
global $product;
?>
<div class="shopAddToCart">
<button value="-" class="minus" >-</button>
<input type="text"
disabled="disabled"
size="2"
value="<?php echo (Check_if_product_in_cart($product->get_id())) ? Check_if_product_in_cart($product->get_id())['QTY'] : 0;
?>"
id="count"
data-product-id= "<?php echo $product->get_id() ?>"
data-in-cart="<?php echo (Check_if_product_in_cart($product->get_id())) ? Check_if_product_in_cart($product->get_id())['in_cart'] : 0;
?>"
data-in-cart-qty="<?php echo (Check_if_product_in_cart($product->get_id())) ? Check_if_product_in_cart($product->get_id())['QTY'] : 0;
?>"
class="quantity qty"
max_value = <?php echo ($product->get_max_purchase_quantity() == -1) ? 1000 : $product->get_max_purchase_quantity(); ?>
min_value = <?php echo $product->get_min_purchase_quantity(); ?>
>
<button type="button" value="+" class="plus" >+</button>
</div>
<?php
}
we need to have function to check if the products is already in cart or not so can modify the quantity:
//Check if Product in Cart Already
function Check_if_product_in_cart($product_ids)
{
foreach (WC()->cart->get_cart() as $cart_item):
$items_id = $cart_item['product_id'];
$QTY = $cart_item['quantity'];
// for a unique product ID (integer or string value)
if ($product_ids == $items_id):
return ['in_cart' => true, 'QTY' => $QTY];
endif;
endforeach;
}
we need to add custom event in order to reduce the quantity:
//Add Event Handler To update QTY
add_action('wc_ajax_update_qty', 'update_qty');
function update_qty()
{
ob_start();
$product_id = absint($_POST['product_id']);
$product = wc_get_product($product_id);
$quantity = $_POST['quantity'];
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item):
if ($cart_item['product_id'] == $product_id) {
WC()->cart->set_quantity($cart_item_key, $quantity, true);
}
endforeach;
wp_send_json('done');
}
Finally We need Javascript to handle the event actions :
jQuery(document).ready(function ($) {
"use strict";
// Add Event Listner on the Plush button
$('.plus').click(function () {
if (parseInt($(this).prev().val()) < parseInt($(this).prev().attr('max_value'))) {
$(this).prev().val(+$(this).prev().val() + 1);
var currentqty = parseInt($(this).prev().attr('data-in-cart-qty')) + 1;
var id = $(this).prev().attr('data-product-id');
var data = {
product_id: id,
quantity: 1
};
$(this).prev().attr('data-in-cart-qty', currentqty);
$(this).parent().addClass('loading');
$.post(wc_add_to_cart_params.wc_ajax_url.toString().replace('%%endpoint%%', 'add_to_cart'), data, function (response) {
if (!response) {
return;
}
if (response) {
var url = woocommerce_params.wc_ajax_url;
url = url.replace("%%endpoint%%", "get_refreshed_fragments");
$.post(url, function (data, status) {
$(".woocommerce.widget_shopping_cart").html(data.fragments["div.widget_shopping_cart_content"]);
if (data.fragments) {
jQuery.each(data.fragments, function (key, value) {
jQuery(key).replaceWith(value);
});
}
jQuery("body").trigger("wc_fragments_refreshed");
});
$('.plus').parent().removeClass('loading');
}
});
}
});
$('.minus').click(function () {
$(this).next().val(+$(this).next().val() - 1);
var currentqty = parseInt($(this).next().val());
var id = $(this).next().attr('data-product-id');
var data = {
product_id: id,
quantity: currentqty
};
$(this).parent().addClass('loading');
$.post(wc_add_to_cart_params.wc_ajax_url.toString().replace('%%endpoint%%', 'update_qty'), data, function (response) {
if (!response) {
return;
}
if (response) {
var url = woocommerce_params.wc_ajax_url;
url = url.replace("%%endpoint%%", "get_refreshed_fragments");
$.post(url, function (data, status) {
$(".woocommerce.widget_shopping_cart").html(data.fragments["div.widget_shopping_cart_content"]);
if (data.fragments) {
jQuery.each(data.fragments, function (key, value) {
jQuery(key).replaceWith(value);
});
}
jQuery("body").trigger("wc_fragments_refreshed");
});
$('.plus').parent().removeClass('loading');
}
});
});
});
Note: This code is tested and working you can check it at
http://dev-ak.com/woocommerce-dev/shop/
You can download the whole files from :
https://github.com/kashalo/wc_qty_ajax_stroefront_child.git
Regarding the Animation part in footer cart that of course can be done, and if i have some free time i will do it too.

Woocommerce - Product Page - How to create AJAX on "Add To Cart" button?

I want to make an "Add To Cart" button on a product page that would work with AJAX. How can I do it? When I add to cart on a product page - it refreshes the page, how can I make it work by AJAX?
The "Add to cart" button on "Quick View" on archive works by ajax - and it's great, but how can I do the same on product page?
I want to click on "Take me Home" on the product page which would then
add the product with the selected attributes to my cart by ajax and will open that cart (like when you hover onto the bag image on menu) and shakes the bag image.
Just add the following attributes to the Add to Cart button to enable the Ajax button.
<a href="<?php echo $product->add_to_cart_url() ?>" value="<?php echo esc_attr( $product->get_id() ); ?>" class="ajax_add_to_cart add_to_cart_button" data-product_id="<?php echo get_the_ID(); ?>" data-product_sku="<?php echo esc_attr($sku) ?>" aria-label="Add “<?php the_title_attribute() ?>” to your cart">
Add to Cart
</a>
The ajax_add_to_cart add_to_cart_button classes, and the data-product_id="<?php echo get_the_ID(); ?>" data-product_sku="<?php echo esc_attr($sku) ?>" attributes are required.
No need to apply any action or filter.
We can use ajax from archive page. it's easy -
Remove old button which submiting form:
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
Add ajax-link from archive page to single product page:
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_loop_add_to_cart', 30 );
P.S. JS Callback. For example you can show popup with links "Back to shop" and "Cart" or "Checkout"
$('body').on('added_to_cart',function(){
// Callback -> product added
//$('.popup').show();
});
Please start by reading this page:
http://codex.wordpress.org/Plugin_API/Action_Reference/wp_ajax_(action)
First you need to add some code to your functions.php for example:
add_action( 'wp_ajax_add_foobar', 'prefix_ajax_add_foobar' );
add_action( 'wp_ajax_nopriv_add_foobar', 'prefix_ajax_add_foobar' );
function prefix_ajax_add_foobar() {
$product_id = intval( $_POST['product_id'] );
// add code the add the product to your cart
die();
}
Then you have to add some javascript code that triggers the add to cart and makes a call to the function:
jQuery( ".add-to-cart" ).each(function()
{
var product_id = jQuery(this).attr('rel');
var el = jQuery(this);
el.click(function() {
var data = {
action: 'add_foobar',
product_id: product_id
};
jQuery.post('/wp-admin/admin-ajax.php' , data, function(response) {
if(response != 0) {
// do something
} else {
// do something else
}
});
return false;
});
});
This is just an example of how it can be done. Although its very basic. This javascript checks for links with the classname .add-to-cart and checks the rel attribute for the corresponding product. It then sends the product id to the php class. There you need to add code to add the corresponding product to the cart.
I suggest you search some more about the topic to make it suit your needs. Good luck.
Woocommerce has come along way. I think the solution is quite easy now. In case I am missing something, all that is required it checking the "Enable AJAX add to cart buttons on archives" and using the woocommerce_template_loop_add_to_cart() function.
The checkbox option is under Woocommerce > Settings > Products > General.
Then simply use woocommerce_template_loop_add_to_cart() wherever you wish to output the button.
If you are using a custom loop like I was, you need to be sure to make the product global in order for the woocommerce_template_loop_add_to_cart() to work.
Below is a small example of using the function:
add_shortcode( 'buy_again' , 'msp_buy_again_shortcode' );
function msp_buy_again_shortcode(){
$order_items = msp_get_customer_unique_order_items( get_current_user_id() );
echo '<div class="owl-carousel owl-theme">';
foreach( $order_items as $id ){
$product = wc_get_product( $id );
global $product;
if( ! empty( $product ) ){
?>
<div class="card buy-again-product">
<a class="link-normal" href="<?php echo $product->get_permalink(); ?>">
<?php echo $product->get_image( 'woocommerce_thumbnail', array( 'class' => 'card-img-top' ) ) ?>
<div class="card-body">
<?php echo wc_get_rating_html( $product->get_average_rating(), $product->get_review_count() ) ?>
<h5><?php echo $product->get_name(); ?></h5>
<p><?php echo $product->get_price_html() ?></p>
<?php woocommerce_template_loop_add_to_cart(); ?>
</div>
</a>
</div>
<?php
}
}
// loop and display buy again.
// try to use the official woocommerce loop.
echo '</div>';
}
Copy this code into your file. For example: my-theme-wc-single-ajax-add-cart.js.
function myThemeWc_SingleProductAddToCart(thisObj) {
if (typeof($) === 'undefined') {
var $ = jQuery.noConflict();
}
var thisForm = thisObj.closest('form');
var button = thisForm.find('.button');
var formUrl = thisForm.attr('action');
var formMethod = thisForm.attr('method');
if (typeof(formMethod) === 'undefined' || formMethod == '') {
formMethod = 'POST';
}
var formData = new FormData(thisForm[0]);
formData.append(button.attr('name'), button.val());
button.removeClass('added');
button.addClass('loading');
myThemeWc_SingleProductCartAjaxTask = $.ajax({
url: formUrl,
method: formMethod,
data: formData,
cache: false,
contentType: false,
processData: false
})
.done(function(data, textStatus, jqXHR) {
$(document.body).trigger('wc_fragment_refresh');
$.when(myThemeWc_SingleProductCartAjaxTask)
.then(myThemeWc_SingleProductUpdateCartWidget)
.done(function() {
button.removeClass('loading');
button.addClass('added');
setTimeout(function() {
button.removeClass('added');
}, 2000);
});
})
.fail(function(jqXHR, textStatus, errorThrown) {
button.removeClass('loading');
})
.always(function(jqXHR, textStatus, errorThrown) {
$('.cart').off('submit');
myThemeWc_SingleProductListenAddToCart();
});
}// myThemeWc_SingleProductAddToCart
function myThemeWc_SingleProductListenAddToCart() {
if (typeof($) === 'undefined') {
var $ = jQuery.noConflict();
}
$('.cart').on('submit', function(e) {
e.preventDefault();
myThemeWc_SingleProductAddToCart($(this));
});
}// myThemeWc_SingleProductListenAddToCart
/**
* Update WooCommerce cart widget by called the trigger and listen to the event.
*
* #returns {undefined}
*/
function myThemeWc_SingleProductUpdateCartWidget() {
if (typeof($) === 'undefined') {
var $ = jQuery.noConflict();
}
var deferred = $.Deferred();
$(document.body).on('wc_fragments_refreshed', function() {
deferred.resolve();
});
return deferred.promise();
}// myThemeWc_SingleProductUpdateCartWidget
var myThemeWc_SingleProductCartAjaxTask;
// on page load --------------------------------------------
jQuery(function($) {
$(document.body).on('wc_fragments_refreshed', function() {
console.log('woocommerce event fired: wc_fragments_refreshed');
});
myThemeWc_SingleProductListenAddToCart();
});
You may need to replace function, variable prefix myThemeWc_ to what you want.
This code use the original WooCommerce single product page add to cart button but stop its functional and then use ajax instead by remain all the values in the form.
Then enqueue this js file.
add_action('wp_enqueue_scripts', 'mythemewc_enqueue_scripts');
function mythemewc_enqueue_scripts() {
if (class_exists('\\WooCommerce') && is_product()) {
wp_enqueue_script('mythemewc-single-product', trailingslashit(get_stylesheet_directory_uri()) . 'assets/js/my-theme-wc-single-ajax-add-cart.js', ['jquery'], false, true);
}
}
You may have to code your css button to make it show the loading, added icon.
Here is css.
.woocommerce #respond input#submit.added::after,
.woocommerce a.btn.added::after,
.woocommerce button.btn.added::after,
.woocommerce input.btn.added::after,
.woocommerce .single_add_to_cart_button.added::after {
font-family: WooCommerce;
content: '\e017';
margin-left: .53em;
vertical-align: bottom;
}
.woocommerce #respond input#submit.loading,
.woocommerce a.btn.loading,
.woocommerce button.btn.loading,
.woocommerce input.btn.loading,
.woocommerce .single_add_to_cart_button.loading {
opacity: .25;
padding-right: 2.618em;
position: relative;
}
.woocommerce #respond input#submit.loading::after,
.woocommerce a.btn.loading::after,
.woocommerce button.btn.loading::after,
.woocommerce input.btn.loading::after,
.woocommerce .single_add_to_cart_button.loading::after {
font-family: WooCommerce;
content: '\e01c';
vertical-align: top;
font-weight: 400;
position: absolute;
right: 1em;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
You can replicate the behavour of the archives button in your single products
add_action('wp_ajax_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
add_action('wp_ajax_nopriv_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart'); function woocommerce_ajax_add_to_cart() {
$product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($_POST['product_id']));
$quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']);
$variation_id = absint($_POST['variation_id']);
$passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity);
$product_status = get_post_status($product_id);
if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id) && 'publish' === $product_status) {
do_action('woocommerce_ajax_added_to_cart', $product_id);
if ('yes' === get_option('woocommerce_cart_redirect_after_add')) {
wc_add_to_cart_message(array($product_id => $quantity), true);
}
WC_AJAX :: get_refreshed_fragments();
} else {
$data = array(
'error' => true,
'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink($product_id), $product_id));
echo wp_send_json($data);
}
wp_die();
}
add_action('wp_ajax_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
add_action('wp_ajax_nopriv_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
function woocommerce_ajax_add_to_cart() {
$product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($_POST['product_id']));
$quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']);
$variation_id = absint($_POST['variation_id']);
$passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity);
$product_status = get_post_status($product_id);
if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id) && 'publish' === $product_status) {
do_action('woocommerce_ajax_added_to_cart', $product_id);
if ('yes' === get_option('woocommerce_cart_redirect_after_add')) {
wc_add_to_cart_message(array($product_id => $quantity), true);
}
WC_AJAX :: get_refreshed_fragments();
} else {
$data = array(
'error' => true,
'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink($product_id), $product_id));
echo wp_send_json($data);
}
wp_die();
}
you can see the full tutorial here
https://quadmenu.com/add-to-cart-with-woocommerce-and-ajax-step-by-step/
I used this plugin for the backend part https://wordpress.org/plugins/woo-ajax-add-to-cart/
I'm not using the product page, so I modified the script to work with any button:
(function($) {
$(document).on('click', '.btn', function(e) {
var $thisbutton = $(this);
try {
var href = $thisbutton.prop('href').split('?')[1];
if (href.indexOf('add-to-cart') === -1) return;
} catch (err) {
return;
}
e.preventDefault();
var product_id = href.split('=')[1];
var data = {
product_id: product_id
};
$(document.body).trigger('adding_to_cart', [$thisbutton, data]);
$.ajax({
type: 'post',
url: wc_add_to_cart_params.wc_ajax_url.replace(
'%%endpoint%%',
'add_to_cart'
),
data: data,
beforeSend: function(response) {
$thisbutton.removeClass('added').addClass('loading');
},
complete: function(response) {
$thisbutton.addClass('added').removeClass('loading');
},
success: function(response) {
if (response.error & response.product_url) {
window.location = response.product_url;
return;
} else {
$(document.body).trigger('added_to_cart', [
response.fragments,
response.cart_hash
]);
$('a[data-notification-link="cart-overview"]').click();
}
}
});
return false;
});
})(jQuery);
info: Tested with WooCommerce 2.4.10.
Hmm, well I did it in another way, used the woocommerce loop from add to cart (woocommerce/templates/loop/add-to-cart.php)
global $product;
echo apply_filters( 'woocommerce_loop_add_to_cart_link',
sprintf( '%s',
esc_url( $product->add_to_cart_url() ),
esc_attr( $product->id ),
esc_attr( $product->get_sku() ),
esc_attr( isset( $quantity ) ? $quantity : 1 ),
$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
esc_attr( $product->product_type ),
esc_html( $product->add_to_cart_text() )
),
$product );
BUT the problem was that it was adding just 1 quantity, in fact, you can see in the code that is listed quantity : 1, so I had problems, until I bumped into this guys who saved me
ps. leaving the 1st part where it adds just 1 product for people who don't need more than 1 product in the basket, but I added a solution for those who need more than just 1 product added to the cart.
add-to-cart.js
jQuery( document ).on( 'click', '.product_type_simple', function() {
var post_id = jQuery(this).data('product_id');//store product id in post id variable
var qty = jQuery(this).data('quantity');//store quantity in qty variable
jQuery.ajax({
url : addtocart.ajax_url, //ajax object of localization
type : 'post', //post method to access data
data :
{
action : 'prefix_ajax_add_foobar', //action on prefix_ajax_add_foobar function
post_id : post_id,
quantity: qty
},
success : function(response){
jQuery('.site-header .quantity').html(response.qty);//get quantity
jQuery('.site-header .total').html(response.total);//get total
//loaderContainer.remove();
alert("Product Added successfully..");
}
});
return false;
});
To make ajax woocomerce work on another page you will need.
goes in functions.php
paste this:
remove_action ('woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30);
add_action ('woocommerce_single_product_summary', 'woocommerce_template_loop_add_to_cart', 30);
in footer.php in the end paste this:
<script>
$ ('body'). on ('add_to_cart', function () {
     // Callback -> product added
     // $ ('. popup'). show ();
});
</script>
For me working exelent. I think this is the simplest solution with Ajax.
+ Add to cart
I used Eh Jewel's answer but then added some custom JS for once the product was added to the cart. This completes the final AJAX process of being able to update the page however you want.
For completeness, here is the HTML code I used (same as Eh Jewel's):
Add to Cart
Then for the custom JS bit:
$(window).on('load', function() {
$('body').on( 'added_to_cart', function( added_to_cart, cart, cart_hash, button ){
// Put the functionality here. Debugging shows you what you have to work with:
console.log('added_to_cart object');
console.log(added_to_cart);
console.log('cart object');
console.log(cart);
console.log('cart_hash object');
console.log(cart_hash);
console.log('button object');
console.log(button);
});
});

Categories