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.
Related
Hi have a wocommerce plugin, While changing the payment method. the cost for shipping my function calculate_shipping is not being called. and therefore shipping methods are not updating with appropriate cost
here are some samples from my code.
public function __construct() {
add_action('woocommerce_review_order_before_payment', array($this, 'update_shipping_charges'), 1);
}
public function update_shipping_charges() {
// jQuery code
?>
<script type="text/javascript">
(function ($) {
$('form.checkout').on('change', 'input[name^="payment_method"]', function () {
// Set the select value in a variable
$('body').trigger('update_checkout');
//testing
$('body').on('updated_checkout', function() {
console.log('updated');
});
});
})(jQuery);
</script>
<?php
}
Try wrapping everything inside the init hook. Maybe the code gets executed too early:
public function __construct() {
add_action( 'init', [ $this, 'init_action' ] );
}
public function init_action(): void {
add_action( 'woocommerce_review_order_before_payment', [ $this, 'update_shipping_charges' ], 1 );
}
public function update_shipping_charges(): void {
// jQuery code
?>
<script type="text/javascript">
(function ( $ ) {
$( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function () {
// Set the select value in a variable
let body = $( 'body' );
body.trigger( 'update_checkout' );
//testing
body.on( 'updated_checkout', function () {
console.log( 'updated' );
} );
} );
})( jQuery );
</script>
<?php
}
You could try multiple hooks if init don't works:
woocommerce_loaded
woocommerce_init
plugins_loaded <- I use this one in my plugins for example
Please try the following (Add to functions.php or via Code Snippets plugin)
function kia_checkout_on_payment_change() {
wp_add_inline_script( 'wc-checkout', '
jQuery( document.body ).on( "payment_method_selected", function() {
jQuery( "form.checkout" ).trigger( "update_checkout", { update_shipping_method: true } );
console.log("payment selected");
} );
'
);
}
add_action( 'wp_enqueue_scripts', 'kia_checkout_on_payment_change' );
A couple notes....
We're adding the script right after the wc-checkout script is loaded.
We're listening for the WooCommerce checkout script's payment_method_selected (but yes, it's a core Woo trigger in the checkout) trigger which should fire when the payment method is changed
We're explicitly passing some arguments to the update_checkout function.
Don't have any shipping methods set up locally to test it properly, but I hope it points you in the right direction.
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.
I am attempting to apply a coupon code to the basket on a button press.
I have the following code:-
coupon = jQuery(this).data('coupon');
data = {coupon_code : coupon};
jQuery.post( "?wc-ajax=apply-coupon", { coupon_code: coupon }).done(function( data ) {
alert( "Data Loaded: " + data );
});
I can see the following data is being parsed to the server:-
coupon_code: 10percentdiscount
The 10percentdiscount exists.
The Server is not sending back a response once I have sent the request.
Am I correctly making this request or is there another way?
Thank you in advance.
You don't need to add custom code in your functions.php. Woocommerce supports adding coupons via AJAX natively (see how below).
Errors in your code:
You forgot to send the nonce (security parameter);
It is apply_coupon not apply-coupon (underscore vs dash);
Your URL should start with a slash "/?wc-ajax=apply_coupon";
Correct version:
var data = {
coupon_code: jQuery(this).data('coupon'),
security: '<?php echo wp_create_nonce("apply-coupon") ?>'
};
jQuery.post('/?wc-ajax=apply_coupon', data).done(function(data) {
alert("Data Loaded: " + data);
});
I would do so:
Define ajax url in header.php or in page would you add coupon
<script type="text/javascript" language="javascript">
var ajax_url = "<?php bloginfo('url'); ?>/wp-admin/admin-ajax.php";
</script>
In function.php you must define ajax call
function implement_ajax() {
include(TEMPLATEPATH . '/ajax_return.php');
}
add_action('wp_ajax_my_special_action', 'implement_ajax');
add_action('wp_ajax_nopriv_my_special_action', 'implement_ajax');
In ajax_return.php you past code that add coupon to woocommerce:
if (isset($_POST['couponcode']))
{ apply_coupon($_POST['couponcode']); };
function apply_coupon($couponcode) {
global $woocommerce; WC()->cart->remove_coupons();
$ret = WC()->cart->add_discount( $couponcode );
$array = array('return' => $ret); print_r($array);
}
exit;
Your jQuery.post will became this:
<script type="text/javascript">
jQuery(function(){
coupon = jQuery(this).data('coupon');
jQuery.post(ajax_url, {action : 'my_special_action', couponcode : coupon}, return_function, 'JSON');
});
function return_function(data)
{
console.log(data.return); //contains true if coupon was applied
}
</script>
If you need, call return_function to manage response.
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 );
});
Straight from WP Codex: http://codex.wordpress.org/AJAX_in_Plugins
I have this in my functions.php:
add_action( 'admin_footer', 'my_action_javascript' );
function my_action_javascript() {
?>
<script type="text/javascript" >
jQuery(document).ready(function($) {
var data = {
'action': 'my_action',
'whatever': 1234
};
// since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
$.post(ajaxurl, data, function(response) {
alert('Got this from the server: ' + response);
});
});
</script>
<?php
}
add_action( 'wp_ajax_my_action', 'my_action_callback' );
function my_action_callback() {
global $wpdb; // this is how you get access to the database
$whatever = intval( $_POST['whatever'] );
$whatever += 10;
echo $whatever;
die(); // this is required to return a proper result
}
And I don't get a response. I do get an alert saying 'Got this from the server: ', but no response. What gives?
Running your code on two separate wordpress installs from within a plugin file (plugin-name.php) and from within functions.php in my theme, it returns the proper value both times. There do not seem to be any errors in your code either.
Is this the only javascript you're including in the admin area?