Update cart with WooCommerce ajax - php

In my woocommerce website, I have changed the cart page, removed the button "update cart" and create 2 buttons to add and remove items of product like I show in this picture:
When I click on the quantity buttons I want to call the same function if I press the button to update the cart.
For this I am using ajax but it doesn't do anything.
First in my function.php file I have this:
function update_my_cart() {
// here update then cart
var_dump("execute");
}
add_action( 'wp_ajax_update_my_cart', 'update_my_cart' ); // If called from admin panel
add_action( 'wp_ajax_nopriv_update_my_cart', 'update_my_cart' );
add_action( 'wp_enqueue_scripts', 'rct_enqueue_scripts' );
if ( ! function_exists( 'rct_enqueue_scripts' ) ) :
function rct_enqueue_scripts() {
wp_enqueue_script( 'rct-js', get_template_directory_uri() . '/js/themeCoffee.js', array(), '1.0', true );
wp_localize_script('rct-js', 'ajax_object', array('ajax_url' => admin_url( 'admin-ajax.php' )));
}
endif;
And in my jquery file I have this:
updatecart = function(qty) {
var currentVal, data, item_hash, request;
currentVal = void 0;
data = void 0;
item_hash = void 0;
currentVal = parseFloat(qty);
request = $.ajax({
url: 'ajax_object.ajax_url',
method: 'POST',
data: {
quantity: currentVal,
action: 'update_my_cart'
},
dataType: 'html'
});
request.done(function(msg) {
alert('cart update ');
});
request.fail(function(jqXHR, textStatus) {
alert('Request failed: ' + textStatus);
});
};
I obtain this error:
Failed to load resource: the server responded with a status of 404 (Not Found)
Because I try to load my_website/cart/ajax_object.ajax_url.
Thanks in advance!

You have forget this essential process:
add_action('wp_enqueue_scripts', 'add_my_ajax_scripts');
function add_my_ajax_scripts() {
// Here you register your script located in a subfolder `js` of your active theme
wp_enqueue_script( 'ajax-script', get_template_directory_uri().'/js/script.js', array('jquery'), '1.0', true );
// Here you are going to make the bridge between php and js
wp_localize_script( 'ajax-script', 'cart_ajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
}
Then you will retrieve "ajaxurl" and "cart_ajax" in your javascript file in "url:":
$.ajax({
url: cart_ajax.ajaxurl,
...
})
Your javascript function will not work. Here are some functional examples of what you need to do:
WooCommerce - auto update total price when quantity changed?
Wordpress passing ajax value to a specific page using Wordpress
Using AJAX With PHP on Your WordPress Site Without a Plugin
How to use Ajax with your WordPress Plugin or Theme?

Since WooCommerce 2.6.0, released June 2016, WooCommerce cart page uses Ajax to update cart totals after clicking on Update cart button.
It's no longer needed to create your own Ajax call, the one assigned to Update cart button can be used.
I created a free plugin Ajax Cart AutoUpdate for WooCommerce which updates cart page and mini cart after changing product quantity and provides some customization options for this process.
The most important thing is to set update delay. If user changes quantity again during this delay, it will be reset to full duration. If it's not implemented and you change quantity from 1 to 10 by clicking on increment button, it will trigger 9 Ajax calls instead of 1.
JQuery code is below, I suggest placing it in js file and enqueuing in dependency with jQuery, then it works with jQuery deferred:
var timeout;
jQuery('div.woocommerce').on('change keyup mouseup', 'input.qty', function(){ // keyup and mouseup for Firefox support
if (timeout != undefined) clearTimeout(timeout); //cancel previously scheduled event
if (jQuery(this).val() == '') return; //qty empty, instead of removing item from cart, do nothing
timeout = setTimeout(function() {
jQuery('[name="update_cart"]').trigger('click');
}, 1000 );
});

Related

Using wordpress action to modify div content

I'm trying to modify a div's content everytime when something is added to the woocommerce shopping cart. For this example the content is gonna be the current total cart value.
So first I created a simple plugin called "test-cart-value" which contains the following code:
<?php
function test_cart_value() {
echo "<div>" . WC()->cart->total . "</div>";
}
add_shortcode('test_cart_value_shortcode', 'test_cart_value');
This works fine, wherever I place the shortcode I get the current cart value after page load.
So, now I want this printed value to updated every time something is added to the cart, without reloading the page. The idea was to use the action hook woocommerce_cart_updated and call the function - so everytime something in the cart changes, the new cart value gets echoed:
function action_woocommerce_cart_updated() {
test_cart_value();
};
// add the action
add_action( 'woocommerce_cart_updated', 'action_woocommerce_cart_updated', 10, 0 );
The problem is, now I'm not able to dynamically add products to the shopping cart. Whenever I hit the "add to cart" button, the loading animation loads forever.
How to do this properly?
I was trying different approaches with Ajax and different Hooks, but so far nothing worked.
Any Ideas? Thanks in advance!
Edit:
So I tried this as my plugin code
function test_cart_value() {
echo "<div id='cart_test'>" . WC()->cart->total . "</div>";
}
add_shortcode('test_cart_value_shortcode', 'test_cart_value');
// define the actions for the two hooks created, first for logged in users and the next for logged out users
add_action("woocommerce_cart_updated", "cart_update");
// define the function to be fired for logged in users
function cart_update() {
$cart = WC()->cart->total;
$result['type'] = "success";
$result['new_cart'] = $cart;
$result = json_encode($result);
//if I uncomment the "die" function, the page won't load
// die();
}
// Fires after WordPress has finished loading, but before any headers are sent.
add_action( 'init', 'script_enqueuer' );
function script_enqueuer() {
// Register the JS file with a unique handle, file location, and an array of dependencies
wp_register_script( "test_script", plugin_dir_url(__FILE__).'test_script.js', array('jquery') );
// localize the script to your domain name, so that you can reference the url to admin-ajax.php file easily
wp_localize_script( 'test_script', 'myAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' )));
// enqueue jQuery library and the script you registered above
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'test_script' );
}
And my test_script.js code:
jQuery(document).ready( function() {
jQuery(".ajax_add_to_cart").click( function(e) {
e.preventDefault();
jQuery.ajax({
type : "post",
dataType : "json",
url : myAjax.ajaxurl,
data : {action: "cart_update"},
success: function(response) {
if(response.type == "success") {
jQuery("#cart_test").html(response.new_cart);
}
else {
alert("Your like could not be added");
}
}
});
});
});
So I thought that the cart_update() function should fire when I press the "ajax_add_to_cart" Button, but I get an error 400.
Any ideas?
Thanks!
made it work with woocommerce_add_to_cart_fragments.

Change Pay button with image on checkout based on Woocommerce chosen payment method

Through this function I can change the text on the pay button.
I would like to insert a small image instead.
add_filter( 'woocommerce_available_payment_gateways', 'woocommerce_available_payment_gateways' );
function woocommerce_available_payment_gateways( $available_gateways ) {
if (! is_checkout() ) return $available_gateways; // stop doing anything if we're not on checkout page.
if (array_key_exists('paypal_express',$available_gateways)) {
// Gateway ID for Paypal is 'paypal'.
$available_gateways['paypal_express']->order_button_text = __( 'PAY', 'woocommerce' );
}
return $available_gateways;
}
Thanks in advance for the help!
As in the frontend the button text will be changed by using .text() function of jQuery, adding html like img tag won't work here.
I suggest instead though to you use javascript with jQuery. It should be something like this:
$( document.body ).on( 'payment_method_selected', function(){
var selectedPaymentMethod = $( '.woocommerce-checkout input[name="payment_method"]:checked' ).attr( 'id' );
$( '#place_order' ).find('.payment-icon');
$( '#place_order' ).prepend('<span class="payment-icon '+ selectedPaymentMethod +'"></span>'); // or any element like from font-awesome.
});
$( document.body ).trigger( 'payment_method_selected' ); // this will trigger on page load, act as initialize the icon.
The script above will add a span tag with classes payment-icon and an ID of the selected payment method. You can then use css to add your icon as background in this span.

Heartbeat refresh browser when page is updated

I am trying to automatically force a browser refresh on a specific page when the page is beeing updated in the backend. I'm trying to achieve by using the Heartbeat API.
I look through all Heartbeat examples i could find but I can't grasp the whole concept of it.
All I am able to do is console.log a string every 15 sec on this specific page.
What I have so far:
https://pastebin.com/ELQ9uJAw
<?PHP
//embed heartbeat api
function heartbeat_test_enqueue($hook_suffix) {
if ( is_page(1105)) {
// Make sure the JS part of the Heartbeat API is loaded.
wp_enqueue_script('heartbeat');
// Output the test JS in footer.
add_action( 'print_footer_scripts', 'heartbeat_test_js', 20 );
//Add filter to receive hook, and specify we need 2 parameters.
add_filter( 'heartbeat_received', 'dw_receive_heartbeat', 10, 2 );
}
}
add_action( 'wp_enqueue_scripts', 'heartbeat_test_enqueue' );
//clientside
function heartbeat_test_js() {
?>
<script>
jQuery(document).ready( function($) {
// Hook into the heartbeat-send
jQuery( document ).on( 'heartbeat-send', function( e, data ) {
//
});
// Listen for the custom event "heartbeat-tick" on $(document). This fire's once every minute that the page is open.
jQuery(document).on( 'heartbeat-tick', function(e, data) {
console.log("tick");
});
});
</script>
<?php
}
//change heartbeat interval time
function m_heartbeat_settings( $settings ) {
$settings['interval'] = 15; //only values between 15 and 60 seconds allowed
return $settings;
}
add_filter( 'heartbeat_settings', 'm_heartbeat_settings' );
//heartbeat api end
?>
I wanted to use the "post_updated" hook to check if the "post_date" has changed. But I dont get how I can use this hook in combination with the Heartbeat API.
Thanks in advance, I am really lost here.
Finally found a way.
//embed heartbeat api
function heartbeat_test_enqueue($hook_suffix) {
if ( is_page(1105)) {
// Make sure the JS part of the Heartbeat API is loaded.
wp_enqueue_script('heartbeat');
// Output the test JS in admin footer.
add_action( 'print_footer_scripts', 'heartbeat_update', 20 );
//Add filter to receive hook, and specify we need 2 parameters.
add_filter( 'heartbeat_received', 'dw_receive_heartbeat', 10, 2 );
}
}
add_action( 'wp_enqueue_scripts', 'heartbeat_test_enqueue' );
//write timestamp file
function write_timestamp($post_ID, $post_after, $post_before){
if ( $post_ID == 1105 ) {
$myfile = fopen("URLtoTextFile/tv.txt", "w") or die("Unable to open file!");
$txt = $post_after->post_modified;
fwrite($myfile, $txt);
fclose($myfile);
}
}
add_action( 'post_updated', 'write_timestamp', 10, 3 );
//clientside
function heartbeat_update() {
?>
<script>
jQuery(document).ready( function($) {
var current_timestamp;
jQuery.ajax({
url: "/tv.txt",
cache: false,
success: function (data){
current_timestamp = data;
}});
// Listen for the custom event "heartbeat-tick" on $(document). This fire's once every 15s that the page is open.
jQuery(document).on( 'heartbeat-tick', function(e, data) {
jQuery.ajax({
url: "/tv.txt",
cache: false,
success: function (data){
if (data != current_timestamp) {
jQuery('body').fadeOut(1000, function(){
location.reload(true);
});
}
}
});
});
});
</script>
<?php
}
//change heartbeat interval time
function m_heartbeat_settings( $settings ) {
$settings['interval'] = 15; //only values between 15 and 60 seconds allowed
return $settings;
}
add_filter( 'heartbeat_settings', 'm_heartbeat_settings' );
//heartbeat api end
What I am doing:
I write the modification date of the page in a .txt file and after every update i hook into the post_updated hook and check if the date changed. and then i just refresh the browser with jQuery.

Add second WooCommerce product to cart via AJAX with checkbox checked

I have unsuccessfully been trying every-which-way to add a conditional second product to the cart on "Add To Cart" if checkbox checked.
I have an order form, and I would like to add a second product to the cart if a checkbox is checked. I started by attempting to add the value through the session or cookie. This worked on Single Product pages, but not with the Add To Cart shortcode [add_to_cart id="XX"]. I thought AJAX was my best chance, but I'm inexperienced with AJAX and can't tell if it's the shortcode or me.
Here is my cheap way to get to Add to Cart on a checkbox submission.
Input:
function sample_input(){
echo '
<form id="myform" action="">
Check this box:
<input type="checkbox" id="add-to-cart" name="16379" /><input type="submit" value="Submit" /></div></form>
';
}
Load scripts:
function enqueue_scripts_styles_init() {
wp_enqueue_script( 'ajax-script', plugins_url( '/js/ajax-testing-script.js', __FILE__ ), array('jquery'), 1.0 ); // jQuery will be included automatically
wp_localize_script( 'ajax-script', 'ajax_object', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) ); // setting ajaxurl
}
add_action('init', 'enqueue_scripts_styles_init');
JQuery:
jQuery(function($){
send_data = function(item) {
$.post(ajax_object.ajaxurl, {
dataType: "json",
data: {'item' : item},
type: "POST",
cache: false
}).done(function(data, status, xml) {
var obj = jQuery.parseJSON(data);
alert(obj.success);
}).fail(function(jqXHR, textStatus, errorThrown) {
}).always(function() {
});
}
$("#show").click(function() {
var $check = $('input#item');
if ($check.is(":checked")) {
alert("Yes");
send_data($check.val());
} else {
alert("box is not checked");
}
});
});
This is a successful method, and gets me the correct product added to cart, a "Yes" alert plus a second alert of 'undefined'. So I think somewhere the AJAX is broken, since I get the 'undefined' alert. Plus, when I change the id, name, and value on the checkbox to id="item" name="item" value="AddOnProduct" and rely on PHP to deliver the Add To Cart, I get no results from the send_data = function(item) {}
If I change the submit button to do_shortcode('[add_to_cart id="517"]'), I get the failed alert "box is not checked" and only product ID is added to the cart. So I think the AJAX isn't set up to handle the add to cart function and my ajax at the same time. In the end, this is what the final code should be doing:
echo '
<form id="myform" action="">
Check this box:
<input type="checkbox" id="item" name="item" value="AddOnProduct" />
<div id="show">' . do_shortcode('[add_to_cart id="517"]') . '</div></form>';
PHP:
function ajax_action_stuff() {
if (isset($_REQUEST['item'])) {
WC()->cart->add_to_cart( 16379 ); //2nd product
} else {
return;
}
}
add_action( 'wp_ajax_ajax_action', 'ajax_action_stuff' );
add_action( 'wp_ajax_nopriv_ajax_action', 'ajax_action_stuff' );
On (#show)click() the ajax should send the product ID to cart and capture a second ID to send to the cart, if "item" was checked. I think if I could successfully pass the value back to PHP I could execute the command in my ajax function. Is it the AJAX or the shortcode add-to-cart?

Woocommerce Payment Method Detection in Checkout Page

I am using woocommerce plugin and braintree extension of woocommerce for payment. I have enabled both card and paypal payment of woocommerce braintree to checkout. I am trying to figure out how to know which payment gateway the user selects before user actually checkouts and pays. Any hooks under woocommerce or braintree to find either credit card radio button or paypal payment radio button is checked for payment.
However i know we can detect the gateway used for the particular order after successful payment but i want the selected gateway information before payment completes within checkout page. Any Help?
You can detect chosen Payment Method with some basic JavaScript on checkout page and run your custom code with PHP by hooking into woocommerce_checkout_update_order_review action.
First,
you also should place JS code on checkout page, checkout template or in header/footer of your theme, so you can detect when the user has changed payment method option and run your own code after that.
JS code:
jQuery(document).ready( function() {
jQuery( "#payment_method_bacs" ).on( "click", function() {
jQuery( 'body' ).trigger( 'update_checkout' );
});
jQuery( "#payment_method_paypal" ).on( "click", function() {
jQuery(document.body).trigger("update_checkout");
});
jQuery( "#payment_method_stripe" ).on( "click", function() {
jQuery(document.body).trigger("update_checkout");
});
});
Notice that for each payment method you have active you should add 'Click' event. It gives you option to fine tune when your custom code is triggered.
To prevent click event to run ONLY ONCE you should add next block of JS code below first one.
jQuery( document ).ajaxStop(function() {
jQuery( "#payment_method_bacs" ).on( "click", function() {
jQuery(document.body).trigger("update_checkout");
});
jQuery( "#payment_method_paypal" ).on( "click", function() {
jQuery(document.body).trigger("update_checkout");
});
jQuery( "#payment_method_stripe" ).on( "click", function() {
jQuery(document.body).trigger("update_checkout");
});
});
It's the same code only that is triggered after ajax.
In both JS blocks of code add your payment options that you are actually use.
After that you put your custom PHP code that hooks into checkout like this:
if ( ! function_exists( 'name_of_your_function' ) ) :
function name_of_your_function( $posted_data) {
// Your code goes here
}
endif;
add_action('woocommerce_checkout_update_order_review', 'name_of_your_function');
This code can be placed in functions.php.
Here is complete PHP code that detects and run when specific payment option is chosen on checkout page:
function name_of_your_function( $posted_data) {
global $woocommerce;
// Parsing posted data on checkout
$post = array();
$vars = explode('&', $posted_data);
foreach ($vars as $k => $value){
$v = explode('=', urldecode($value));
$post[$v[0]] = $v[1];
}
// Here we collect payment method
$payment_method = $post['payment_method'];
// Run code custom code for each specific payment option selected
if ($payment_method == "paypal") {
// Your code goes here
}
elseif ($payment_method == "bacs") {
// Your code goes here
}
elseif ($payment_method == "stripe") {
// Your code goes here
}
}
add_action('woocommerce_checkout_update_order_review', 'name_of_your_function');
I hope this helps!
This is a very powerful option to run all your custom logic on the checkout page!

Categories