I have woocommerce setup with products and variations on these products. When I change the variation (for example, the size of the product (340g or 900g), I want it to dynamically on the page update the price so the person can see what the price difference is between the two sizes. At the moment, I can't even get the variation ID of the variation. This does not seem to be working at all.
If I test and modify the variations, this is all I get from the Javascript console:
Here is my code:
// removing the price of variable products
remove_action( 'woocommerce_single_product_summary','woocommerce_template_single_price', 10 );
// Change location of
add_action( 'woocommerce_single_product_summary', 'custom_wc_template_single_price', 10 );
function custom_wc_template_single_price(){
global $product;
// Variable product only
if($product->is_type('variable')):
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice && $product->is_on_sale() ) {
$price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
}
?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
}
</style>
<script>
jQuery(document).ready(function($) {
$('select').blur( function(){
console.log("blur");
if( '' != $('input.variation_id').val() ){
console.log($('input.variation_id'));
console.log($('input.variation_id').val());
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('p.availability'))
$('p.availability').remove();
console.log('NULL');
}
});
});
</script>
<?php
echo '<p class="price">'.$price.'</p>
<div class="hidden-variable-price" >'.$price.'</div>';
endif;
}
Here is the site: https://bricksandmortar.ca/product/no-eye-contact/#
Any ideas?
You can hook into the show_variation trigger with some jQuery to get all of the information about the selected variation. Here's an example that will write the price formatted in HTML to the console.
(function( $ ) {
'use strict';
$(function() {
var $variation_form = $( '.variations_form' );
$variation_form.on( "show_variation", function ( event, variation ) {
// Fired when the user selects all the required attributes
console.log(variation.price_html);
} );
});
})( jQuery );
Related
First of all, I have no idea how old and / or deprecated (that's the word right?) this code is. My old developer (passed away) gave it to me well over two years ago, and now I am trying to make sense of it all.
Not being a programmer, I need help with two things, whereof the second part is the most important. When ALL products are removed from the checkout, redirect to the shop page.
This is the code I am using for adding qty and what not to the checkout.
add_filter( 'woocommerce_cart_item_name', 'jess_product_thumbnail_on_checkout_order_review', 20, 3 );
function jess_product_thumbnail_on_checkout_order_review( $product_name, $cart_item, $cart_item_key ) {
if ( is_checkout() ) {
$product = $cart_item['data'];
$thumbnail = $product->get_image(array(50, 50));
$image_html = '<div class="product-item-thumbnail">' . $thumbnail . '</div>';
$product_name_link = '' . $product_name . '';
$product_name = $image_html . $product_name_link;
}
return $product_name;
}
add_action( 'wp_footer', 'jess_product_image_css_checkout', 900 );
function jess_product_image_css_checkout(){
if (is_checkout()){ ?>
<style>
.product-item-thumbnail{float:left; padding-right:20px;}
.product-item-thumbnail img{margin:0!important;}
</style>
<?php
}}
add_filter('woocommerce_checkout_cart_item_quantity', 'jess_qty_change_remove_item_checkout_order_review', 1000, 3);
function jess_qty_change_remove_item_checkout_order_review( $quantity_html, $cart_item, $cart_item_key ) {
$_product = $cart_item['data'];
if ($_product->is_sold_individually()){
$product_quantity = sprintf('<input type="hidden" name="cart[%s][qty]" value="" />', $cart_item_key);
}else{
$product_quantity = woocommerce_quantity_input(
array(
'input_name' => "cart[{$cart_item_key}][qty]",
'input_value' => $cart_item['quantity'],
'max_value' => $_product->get_max_purchase_quantity(),
'min_value' => '1',
'class' => 'qtyinput',
'placeholder' => 'Qty',
'product_name' => $_product->get_name(),
),
$_product,
false
);
}
$cart = WC()->cart->get_cart();
foreach ($cart as $cart_key => $cart_value){
if ($cart_key == $cart_item_key){
$product_id = $cart_item['product_id'];
$_product = $cart_item['data'] ;
$remove_product = sprintf(
'Remove',
esc_url(wc_get_cart_remove_url($cart_key)),
__( 'Remove From My Order', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $_product->get_sku() ),
esc_attr( $cart_item_key )
);
}}
return '<br><span class="product-quantity">' . sprintf( 'Qty: %s', $cart_item['quantity'] ) . ' / ' . $remove_product . '</span>'.$product_quantity.'';
}
add_action( 'wp_footer', 'refresh_checkout_on_quantity_change' );
function refresh_checkout_on_quantity_change() {
if (is_checkout()){ ?>
<script type="text/javascript">
<?php $admin_url = get_admin_url(); ?>
jQuery("form.checkout").on("change", "input.qty", function(){
var data = {
action: 'update_order_qty',
security: wc_checkout_params.update_order_review_nonce,
post_data: jQuery('form.checkout').serialize()
};
jQuery.post('<?php echo $admin_url; ?>' + 'admin-ajax.php', data, function(response){
jQuery('body').trigger('update_checkout');
});
});
</script>
<?php
}}
add_action( 'init', 'jess_load_ajax_checkout_qty_and_removal' );
function jess_load_ajax_checkout_qty_and_removal(){
if (!is_user_logged_in()){
add_action( 'wp_ajax_nopriv_update_order_qty', 'update_order_qty');
}else{
add_action( 'wp_ajax_update_order_qty', 'update_order_qty');
}}
function update_order_qty(){
$values = array();
parse_str($_POST['post_data'], $values);
$cart = $values['cart'];
foreach ($cart as $cart_key => $cart_value){
WC()->cart->set_quantity( $cart_key, $cart_value['qty'], false );
WC()->cart->calculate_totals();
woocommerce_cart_totals();
}
exit;
}
add_action( 'wp_footer', 'jess_remove_product_from_checkout_script' );
function jess_remove_product_from_checkout_script() { ?>
<script>
jQuery( function($){
if (typeof woocommerce_params === 'undefined')
return false;
console.log('defined');
$(document).on('click', 'tr.cart_item a.remove-product', function (e){
e.preventDefault();
var product_id = $(this).attr("data-product_id"),
cart_item_key = $(this).attr("data-cart_item_key"),
product_container = $(this).parents('.shop_table');
product_container.block({
message: null,
overlayCSS: {
cursor: 'none'
}
});
$.ajax({
type: 'POST',
dataType: 'json',
url: wc_checkout_params.ajax_url,
data: {
action: "product_remove",
product_id: product_id,
cart_item_key: cart_item_key
},
success: function (result) {
$('body').trigger('update_checkout');
console.log(result);
}
});
});
});
</script>
<?php
}
add_action('wp_ajax_product_remove', 'ajax_product_remove');
add_action('wp_ajax_nopriv_product_remove', 'ajax_product_remove');
function ajax_product_remove(){
ob_start();
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
if($cart_item['product_id'] == $_POST['product_id'] && $cart_item_key == $_POST['cart_item_key'] ) {
WC()->cart->remove_cart_item($cart_item_key);
}
}
WC()->cart->calculate_totals();
WC()->cart->maybe_set_cart_cookies();
woocommerce_order_review();
$woocommerce_order_review = ob_get_clean();
}
Here is the modified code. I have added some comments where what is changed. This is tested on storefront theme and works.
//We need to load cart scripts
function checkout_woocommerce_scripts()
{
if ( is_checkout() ) wp_enqueue_script( 'wc-cart' );
}
add_action( 'wp_enqueue_scripts', 'checkout_woocommerce_scripts', 10 );
//When we remove all products from checkout will redirect to cart so we redirect to shop instead
//This also will work if we are on cart page and remove all products
add_action('template_redirect','redirect_cart_page');
function redirect_cart_page() {
if(is_cart() && WC()->cart->get_cart_contents_count() == 0 ):
wp_safe_redirect(wc_get_page_permalink( 'shop' ));
endif;
}
add_filter( 'woocommerce_cart_item_name', 'jess_product_thumbnail_on_checkout_order_review', 20, 3 );
function jess_product_thumbnail_on_checkout_order_review( $product_name, $cart_item, $cart_item_key ) {
if ( is_checkout() ) {
$product = $cart_item['data'];
$thumbnail = $product->get_image(array(50, 50));
$image_html = '<div class="product-item-thumbnail">' . $thumbnail . '</div>';
$product_name_link = '' . $product_name . '';
$product_name = $image_html . $product_name_link;
}
return $product_name;
}
add_action( 'wp_footer', 'jess_product_image_css_checkout', 900 );
function jess_product_image_css_checkout(){
if (is_checkout()){ ?>
<style>
.product-item-thumbnail{float:left; padding-right:20px;}
.product-item-thumbnail img{margin:0!important;}
</style>
<?php
}
}
//In this function all i did change is the class of the remove button from remove-product to product-remove
add_filter('woocommerce_checkout_cart_item_quantity', 'jess_qty_change_remove_item_checkout_order_review', 1000, 3);
function jess_qty_change_remove_item_checkout_order_review( $quantity_html, $cart_item, $cart_item_key ) {
$_product = $cart_item['data'];
if ($_product->is_sold_individually()){
$product_quantity = sprintf('<input type="hidden" name="cart[%s][qty]" value="" />', $cart_item_key);
}else{
$product_quantity = woocommerce_quantity_input(
array(
'input_name' => "cart[{$cart_item_key}][qty]",
'input_value' => $cart_item['quantity'],
'max_value' => $_product->get_max_purchase_quantity(),
'min_value' => '1',
'class' => 'qtyinput',
'placeholder' => 'Qty',
'product_name' => $_product->get_name(),
),
$_product,
false
);
}
$cart = WC()->cart->get_cart();
foreach ($cart as $cart_key => $cart_value){
if ($cart_key == $cart_item_key){
$product_id = $cart_item['product_id'];
$_product = $cart_item['data'] ;
$remove_product = sprintf(
'Remove',
esc_url(wc_get_cart_remove_url($cart_key)),
__( 'Remove From My Order', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $_product->get_sku() ),
esc_attr( $cart_item_key )
);
}
}
return '<br><span class="product-quantity">' . sprintf( 'Qty: %s', $cart_item['quantity'] ) . ' / ' . $remove_product . '</span>'.$product_quantity.'';
}
// I have added wc_fragment_refresh to update your minicart when qty change.
add_action( 'wp_footer', 'refresh_checkout_on_quantity_change' );
function refresh_checkout_on_quantity_change() {
if (is_checkout()){ ?>
<script type="text/javascript">
<?php $admin_url = get_admin_url(); ?>
jQuery("form.checkout").on("change", "input.qty", function(){
var data = {
action: 'update_order_qty',
security: wc_checkout_params.update_order_review_nonce,
post_data: jQuery('form.checkout').serialize()
};
jQuery.post('<?php echo $admin_url; ?>' + 'admin-ajax.php', data, function(response){
jQuery('body').trigger( 'wc_fragment_refresh' );
jQuery('body').trigger('update_checkout');
});
});
</script>
<?php
}
}
// You dont need to wrap this in a function and do checks wp_ajax_nopriv runs for guests where wp_ajax runs for users
add_action( 'wp_ajax_nopriv_update_order_qty', 'update_order_qty');
add_action( 'wp_ajax_update_order_qty', 'update_order_qty');
function update_order_qty(){
$values = array();
parse_str($_POST['post_data'], $values);
$cart = $values['cart'];
foreach ($cart as $cart_key => $cart_value){
WC()->cart->set_quantity( $cart_key, $cart_value['qty'], false );
WC()->cart->calculate_totals();
woocommerce_cart_totals();
}
exit;
}
This is i think the better solution when we want to update cart items in checkout. Its all woocommerce core so it will perform and last longer than custom code for people who are not into coding.
Here is a video how its working https://webm.red/iV0t . It may get deleted after time.
//We need to load cart scripts
function checkout_woocommerce_scripts()
{
if ( is_checkout() ) wp_enqueue_script( 'wc-cart' );
}
add_action( 'wp_enqueue_scripts', 'checkout_woocommerce_scripts', 10 );
//If we want to redirect to shop page when cart or checkout get empty.
add_action('template_redirect','redirect_cart_page');
function redirect_cart_page() {
if(is_cart() && WC()->cart->get_cart_contents_count() == 0 ):
wp_safe_redirect(wc_get_page_permalink( 'shop' ));
endif;
}
//Load the cart form provided by woocommerce as shortcode.
// I will keep it outside the checkout form since its a form on its self.
// If we want we can extend the layout with modifying the checkout template.
add_action('woocommerce_before_checkout_form','checkout_cart_form');
function checkout_cart_form() {
echo do_shortcode('[woocommerce_cart]');
}
//Since we load cart form we dont need the coupon form twice
//Remove checkout coupon form comment this if you want to use this instead
remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 );
//Remove cart coupon form
function hide_coupon_field_on_cart( $enabled ) {
if ( is_cart() ) { $enabled = false; } return $enabled;
}
//Uncomment this if you want to use this coupon form
// add_filter( 'woocommerce_coupons_enabled', 'hide_coupon_field_on_cart' );
//The scripts and styles we gonna use. Feel free to move them in your theme css js files (make sure they are loaded on checkout page)
add_action( 'wp_footer', 'checkout_styles_scripts');
function checkout_styles_scripts() {
?>
<style>
body.woocommerce-checkout button[name="update_cart"],
body.woocommerce-checkout input[name="update_cart"] {
display: none;
}
</style>
<script>
jQuery( function( $ ) {
let timeout;
$('.woocommerce').on( 'change keyup mouseup', 'input.qty', function(){
if ( timeout !== undefined ) {
clearTimeout( timeout );
}
timeout = setTimeout(function() {
$("[name='update_cart']").trigger("click"); // trigger cart update
}, 1000 ); // 1 second delay, half a second (500) seems comfortable too
});
} );
</script>
<?php
}
I modified this script to make a shortcode that shows how much the customer need to spend to get free shipping.
/**
* #author Rodolfo Melogli
* #compatible WooCommerce 3.9
* #donate $9 https://businessbloomer.com/bloomer-armada/
*/
add_shortcode ('woo_freeshipping_target', 'woo_freeship_target' );
function woo_freeship_target() {
ob_start();
$min_amount = 279; //change this to your free shipping threshold
$current = WC()->cart->subtotal;
if ( $current < $min_amount ) {
$added_text = wc_price( $min_amount - $current );
$notice = sprintf( $added_text );
echo '<span> You need to add '.$notice.'</span>';
}
else if ( $current >= $min_amount ) {
echo '<span>Free Shipping!</span>';
}
return ob_get_clean();
}
But I cannot figure out how can I make it to auto update when the items quantity is modified. Any idea?
To ajaxify your message so it updates when the subtotal change (via ajax) use the woocommerce_add_to_cart_fragments filter hook
So you get:
function custom_message() {
// Initialize
$message = __( 'Default message', 'woocommerce' );
// True
if ( WC()->cart ) {
// Change this to your free shipping threshold
$min_amount = 279;
// Get cart subtotal
$subtotal = WC()->cart->get_subtotal();
if ( $subtotal < $min_amount ) {
$message = sprintf( __( 'You need to add %s to get free shipping', 'woocommerce' ), wc_price( $min_amount - $subtotal ) );
} else {
$message = __( 'Free shipping', 'woocommerce' );
}
}
return $message;
}
// Refreshing on cart ajax events
function filter_woocommerce_add_to_cart_fragments( $fragments ) {
$fragments['div.display-message'] = '<div class="display-message">' . custom_message() . '</div>';
return $fragments;
}
add_filter( 'woocommerce_add_to_cart_fragments', 'filter_woocommerce_add_to_cart_fragments', 10, 1 );
// Shortcode
function display_my_message() {
return '<div class="display-message">' . custom_message() . '</div>';
}
// Register shortcode
add_shortcode( 'display_message', 'display_my_message' );
SHORTCODE USAGE
In an existing page:
[display_message]
Or in PHP:
echo do_shortcode("[display_message]");
Related: WooCommerce shortcode to ajaxify message that display: "Buy X more products to get a discount"
I read a few topics like "Javascript inside PHP doesn't work" but I couldn't find a solution. I have a WP plugin that sends emails when someone clicks on a button. Also when an email has been sent a PHP pop-up with confirmation appears. I think it's in the part where "wp_mail()" is. When an email was sent properly, I want to run some JS, right before PHP message. So I tried to do this outside PHP (first attempt) and through echo (second attempt below). I don't see these console logs. Also when I have this JS there, then this PHP alert doesn't show. When I remove it, it works. This code is run for sure because when I change the text in PHP alert message I see it. Also above this function is another function "add_action('wp_footer'..) and there is only JS, and this JS works, when I change something. I can't understand why it doesn't work there.
Function where I have problem:
function updateRequest()
{
$admin_email = get_option('admin_email');
$senderEmail = empty(trim(get_option('settings_page_sender_email'))) ? "no-reply#".$_SERVER['HTTP_HOST'] : get_option('settings_page_sender_email');
$order = wc_get_order($_POST['orderID']);
$title = empty(trim(get_option('settings_page_email_title')))?"“[UPDATE REQUEST]”":get_option('settings_page_email_title');
$recipient = $admin_email;
$subject = str_replace('[PRODUCTTITLE]', $_POST['productTitle'], $title);
$message = " ";
$headers = array(
'Content-Type: text/html; charset=UTF-8',
'From: '.$_POST['name'].' <'.$senderEmail.'>',
'Reply-To: '.$_POST['name'].' <'.$_POST['email'].'>'
);
if(wp_mail( $recipient, $subject, $message, $headers )){
?>
<script type="text/javascript">console.log("Data alert");</script>
<?php
echo'<script type="text/javascript">console.log("Data alert");</script>';
$confirmationTxt = empty(trim(get_option('settings_page_confirmation_text'))) ? "Request has been sent" : get_option('settings_page_confirmation_text');
wp_send_json_success($confirmationTxt , $status_code = null );
}else{
wp_send_json_error( "Something Went Wrong ...!", $status_code );
}
}
And this is the whole file
<?php
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
function console_log($output, $with_script_tags = true) {
$js_code = 'console.log(' . json_encode($output, JSON_HEX_TAG) .
');';
if ($with_script_tags) {
$js_code = '<script>' . $js_code . '</script>';
}
echo $js_code;
}
/**
* Currently plugin version.
* Start at version 1.0.0 and use SemVer - https://semver.org
* Rename this for your plugin and update it as you release new versions.
*/
define( 'VIRTUAL_PRODUCT_WOOCOMMERCE_UPDATE_REQUEST_VERSION', '1.0.0' );
// Define global constants
$plugin_data = get_file_data( __FILE__, array( 'name'=>'Plugin Name', 'version'=>'Version', 'text'=>'Text Domain' ) );
function VPWUR_constants( $constant_name, $value ) {
$constant_name_prefix = 'VPWUR_VERSION';
$constant_name = $constant_name_prefix . $constant_name;
if ( !defined( $constant_name ) )
define( $constant_name, $value );
}
VPWUR_constants( 'DIR', dirname( plugin_basename( __FILE__ ) ) );
VPWUR_constants( 'BASE', plugin_basename( __FILE__ ) );
VPWUR_constants( 'URL', plugin_dir_url( __FILE__ ) );
VPWUR_constants( 'PATH', plugin_dir_path( __FILE__ ) );
VPWUR_constants( 'SLUG', dirname( plugin_basename( __FILE__ ) ) );
VPWUR_constants( 'NAME', $plugin_data['name'] );
VPWUR_constants( 'VERSION', $plugin_data['version'] );
VPWUR_constants( 'TEXT', $plugin_data['text'] );
VPWUR_constants( 'PREFIX', '' );
VPWUR_constants( 'SETTINGS', '' );
/**
* The code that runs during plugin activation.
* This action is documented in includes/class-virtual-product-woocommerce-update-request-activator.php
*/
function activate_virtual_product_woocommerce_update_request() {
require_once plugin_dir_path( __FILE__ ) . 'includes/class-virtual-product-woocommerce-update-request-activator.php';
Virtual_Product_Woocommerce_Update_Request_Activator::activate();
}
/**
* The code that runs during plugin deactivation.
* This action is documented in includes/class-virtual-product-woocommerce-update-request-deactivator.php
*/
function deactivate_virtual_product_woocommerce_update_request() {
require_once plugin_dir_path( __FILE__ ) . 'includes/class-virtual-product-woocommerce-update-request-deactivator.php';
Virtual_Product_Woocommerce_Update_Request_Deactivator::deactivate();
}
register_activation_hook( __FILE__, 'activate_virtual_product_woocommerce_update_request' );
register_deactivation_hook( __FILE__, 'deactivate_virtual_product_woocommerce_update_request' );
/**
* The core plugin class that is used to define internationalization,
* admin-specific hooks, and public-facing site hooks.
*/
require plugin_dir_path( __FILE__ ) . 'includes/class-virtual-product-woocommerce-update-request.php';
/**
* Begins execution of the plugin.
*
* Since everything within the plugin is registered via hooks,
* then kicking off the plugin from this point in the file does
* not affect the page life cycle.
*
* #since 1.0.0
*/
function run_virtual_product_woocommerce_update_request() {
$plugin = new Virtual_Product_Woocommerce_Update_Request();
$plugin->run();
}
run_virtual_product_woocommerce_update_request();
add_action('wp_footer', function ()
{
echo "<br><br><br><br><br>";
echo 'Hamza';
if (shortcode_exists( 'UpdateRequstBtn' )) {
echo "<pre>Shortcode Registered</pre>";
}
});
/* Adding CSS style for public */
function my_enqueued_assets() {
wp_enqueue_style('virtual-product-woocommerce-update-request-public', plugin_dir_url(__FILE__) . '/public/css/virtual-product-woocommerce-update-request-public.css', '', time());
}
add_action('wp_enqueue_scripts', 'my_enqueued_assets');
function updateRequstBtn($atts) {
global $product, $woocommerce;
$html = "";
if (method_exists($product, 'get_id')) {
$id = $product->get_id();
}
$atts = shortcode_atts( array(
'id' => #$id,
), $atts, 'UpdateRequstBtn' );
// echo $atts['id'];
$product = new WC_Product($atts['id']);
if (empty($atts['id']) || $atts['id'] == 0 || !get_current_user_id()) {
return;
}
$order = has_bought_items([$atts['id']]);
if (!$order) {
// you can remove this no orders from here ... just remove the text "No Orders"
return "";
}
// // print_r($order->get_billing_email());
$btnText = empty(trim(get_option( 'settings_page_btn_txt' ))) ? "Update Request": get_option( 'settings_page_btn_txt' );
$html .= '<div class="woocommerce-product-gallery vpwur-button-div">';
$html .= '<a href="javascript:void(0)" onclick="updateRequest(this);" class="button vpwur-button-a"
data-email="'.$order->get_billing_email().'"
data-orderID="'.$order->get_id().'"
data-productTitle="'.get_the_title($atts['id']).'"
data-name="'.$order->get_billing_first_name()." ".$order->get_billing_last_name().'"
>'. $btnText .'</a>';
$html .= '<p class="vpwur-sending-txt-pre">Trwa wysylanie zadania...</div>';
return $html;
}
add_shortcode( 'UpdateRequstBtn', 'UpdateRequstBtn' );
/**
* Show number list of downloadable files for group product
*
* #param array $download
* #return void
*/
/*function prefix_downloads_column_download_file( array $download ) {
// print_r($download);
echo '<a href="', $download['download_url'], '" download>', $download['download_name'], '</a>';
// do_shortcode( '[UpdateRequstBtn id="'.$download['product_id'].'"]' );
// echo shortcode_exists( 'UpdateRequstBtn' );
}
add_action( 'woocommerce_account_downloads_column_download-file', 'prefix_downloads_column_download_file' );*/
add_action( 'woocommerce_account_downloads_column_update-request', function( $download ) {
if (get_option( 'enable_download_page_btn' )) {
echo do_shortcode( '[UpdateRequstBtn id="'.$download['product_id'].'"]' );
}
} );
add_filter( 'woocommerce_account_downloads_columns', function( $columns ) {
if (get_option( 'enable_download_page_btn' )) {
// Add Column
$columnName = empty(trim(get_option( 'download_page_column_name' ))) ? "Update Request": get_option( 'download_page_column_name' );
$columns['update-request'] = $columnName;
}
// Return
return $columns;
} );
add_action('wp_footer', function ()
{
?>
<script type="text/javascript">
function updateRequest(e) {
var data = {
'action': 'updateRequest',
'name': e.dataset.name, // We pass php values differently!
'email': e.dataset.email, // We pass php values differently!
'orderID': e.dataset.orderid, // We pass php values differently!
'productTitle': e.dataset.producttitle, // We pass php values differently!
};
// console.log(data);
jQuery.post('<?php echo admin_url('admin-ajax.php') ?>', data, function(response) {
alert(response.data);
// alert('Got this from the server: ' + response);
});
/* Changing CSS for sending email message under button */
const confirmTxtsList = Array.from(document.getElementsByClassName('vpwur-sending-txt-pre'));
confirmTxtsList.forEach(p => {
p.classList.remove('vpwur-sending-txt-pre');
p.classList.add('vpwur-sending-txt-on');
});
}
</script>
<?php
});
add_action('wp_ajax_updateRequest','updateRequest');
add_action('wp_ajax_nopriv_updateRequest','updateRequest');
function updateRequest()
{
$admin_email = get_option('admin_email');
$senderEmail = empty(trim(get_option('settings_page_sender_email'))) ? "no-reply#".$_SERVER['HTTP_HOST'] : get_option('settings_page_sender_email');
$order = wc_get_order($_POST['orderID']);
$title = empty(trim(get_option('settings_page_email_title')))?"“[UPDATE REQUEST]”":get_option('settings_page_email_title');
$recipient = $admin_email;
$subject = str_replace('[PRODUCTTITLE]', $_POST['productTitle'], $title);
$message = " ";
$headers = array(
'Content-Type: text/html; charset=UTF-8',
'From: '.$_POST['name'].' <'.$senderEmail.'>',
'Reply-To: '.$_POST['name'].' <'.$_POST['email'].'>'
);
if(wp_mail( $recipient, $subject, $message, $headers )){
?>
<script type="text/javascript">console.log("Data alert");</script>
<?php
echo'<script type="text/javascript">console.log("Data alert");</script>';
$confirmationTxt = empty(trim(get_option('settings_page_confirmation_text'))) ? "Request has been sent" : get_option('settings_page_confirmation_text');
wp_send_json_success($confirmationTxt , $status_code = null );
}else{
wp_send_json_error( "Something Went Wrong ...!", $status_code );
}
}
function has_bought_items($prod_arr=[]) {
$bought = false;
// Set HERE ine the array your specific target product IDs
// $prod_arr = array( '21', '67' );
// Get all customer orders
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => get_current_user_id(),
'post_type' => 'shop_order', // WC orders post type
'post_status' => 'wc-completed' // Only orders with status "completed"
) );
foreach ( $customer_orders as $customer_order ) {
// Updated compatibility with WooCommerce 3+
$order_id = method_exists( $customer_order, 'get_id' ) ? $customer_order->get_id() : $customer_order->id;
$order = wc_get_order( $customer_order );
// Iterating through each current customer products bought in the order
foreach ($order->get_items() as $item) {
// WC 3+ compatibility
if ( version_compare( WC_VERSION, '3.0', '<' ) )
$product_id = $item['product_id'];
else
$product_id = $item->get_product_id();
// Your condition related to your 2 specific products Ids
if ( in_array( $product_id, $prod_arr ) )
$bought = $order;
}
}
// return "true" if one the specifics products have been bought before by customer
return $bought;
}
PS there is no "?>" at the end, as this is main plugin file and must be part of some other file probably.
So I was looking for a way to update Pricing for a variable Product (Woocommerce + WP), without showing the Price Range + Final Price (including Variables).
I stumbled upon this script, which seems to work perfectly for my use case. Source - Stackoverflow
It works fine on mobile.
However, in Desktop Browser, it requires me to click on a random place of the page to update the pricing. This is very inconvenient.
Any idea how to fix this?
My coding skills are limited to HTML/CSS and very basic js.
Any help is appreciated.
This is the code:
add_action( 'woocommerce_before_single_product', 'check_if_variable_first' );
function check_if_variable_first(){
if ( is_product() ) {
global $post;
$product = wc_get_product( $post->ID );
if ( $product->is_type( 'variable' ) ) {
// removing the price of variable products
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
// Change location of
add_action( 'woocommerce_single_product_summary', 'custom_wc_template_single_price', 10 );
function custom_wc_template_single_price(){
global $product;
// Variable product only
if($product->is_type('variable')):
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice && $product->is_on_sale() ) {
$price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
}
?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
}
</style>
<script>
jQuery(document).ready(function($) {
$('select').blur( function(){
if( '' != $('input.variation_id').val() ){
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('p.availability'))
$('p.availability').remove();
console.log('NULL');
}
});
});
</script>
<?php
echo '<p class="price">'.$price.'</p>
<div class="hidden-variable-price" >'.$price.'</div>';
endif;
}
}
}
}
LINK to Image for Usecase explanation - See also Stackoverflow Link where I took the code from
The problem which you are facing seems to be the $('select').blur().
As you want this to change automatically, I suggest changing this to change()..
<script>
jQuery(document).ready(function($) {
$('select').change( function(){
if( '' != $('input.variation_id').val() ){
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('p.availability'))
$('p.availability').remove();
console.log('NULL');
}
});
});
</script>
The blur() event occurs when an object loses focus.. In your case, when you click off the screen.
the change() event occurs when the object changes.. In your case, whenever the select option changes
The code above was flawed.
I found a better solution for my use case in this post: Update Woo Variable Price
I would like to have WooCommerce external/affiliate products open in a new tab. This would go for all aspects of a product: image, title, buy now button and archive pages(product category/tags). All I have been able to find is a way to change the "Buy Now" button but no other solutions to the other areas previously mentioned. Other solutions offer a the external link in all the right places(product image, title, buy now button, archive pages), but it can't open in a new tab.
I've tried a bunch of different codes, as mentioned above, all lead to partial solutions. I believe if these can be combined, it may work. But I haven't been successful.
add_action( 'template_redirect', 'redirect_external_products' );
function redirect_external_products() {
global $post;
if ( is_singular( 'product' ) && ! empty( $post ) && ( $product = wc_get_product( $post ) ) && $product->is_type( 'external' ) ) {
wp_redirect( $product->get_product_url() );
exit;
}
}
function custom_redirect() {
global $post;
if( is_single() ){
$external_link = get_post_meta( $post->ID, 'external_link', true );
if($external_link) {
echo "<script> window.open(".$external_link.", '_blank') </script>";
exit;
}
}
}
I would like all affiliate/external links to open in a new tab. This would include: product image, product title, buy now button, archive page listings(product category/tags).
All previous attempts will only open the Buy Now links in a new tab - but the image and title still direct to the single product page. The first code above from does the trick, but won't open in a new tab. My research tells me that when using the template_redirect function, link targeting is not possible.
remove the previous code and let's add this code in the theme's functions.php file.
add_filter( 'woocommerce_loop_product_link', 'filter_external_product_permalink', 10, 2 );
if ( ! function_exists( 'filter_external_product_permalink' ) ) {
/**
* Insert the external url for products in the loop.
*/
function filter_external_product_permalink( $the_permalink, $product ){
global $product;
if( $product->is_type( 'external' ) ) {
$external_link = $product->get_product_url();
return $external_link;
}
return $the_permalink;
}
}
if ( ! function_exists( 'woocommerce_template_loop_product_link_open' ) ) {
/**
* Insert the opening anchor tag for products in the loop.
*/
function woocommerce_template_loop_product_link_open() {
global $product;
$link = apply_filters( 'woocommerce_loop_product_link', get_the_permalink(), $product );
$link_target = $product->is_type( 'external' ) ? '_blank' : '_self';
echo '<a target="' . esc_attr( $link_target ).'" href="' . esc_url( $link ) . '" class="woocommerce-LoopProduct-link woocommerce-loop-product__link">';
}
}
add_filter( 'woocommerce_loop_add_to_cart_link', 'custom_external_add_product_link' , 10, 2 );
if ( ! function_exists( 'custom_external_add_product_link' ) ) {
function custom_external_add_product_link( $permalink ) {
global $product;
if ( $product->is_type( 'external' ) ) {
$permalink = sprintf( '<a rel="nofollow" href="%s" data-quantity="%s" data-product_id="%s" data-product_sku="%s" class="%s" target="_blank">%s</a>',
esc_url( $product->add_to_cart_url() ),
esc_attr( isset( $quantity ) ? $quantity : 1 ),
esc_attr( $product->id ),
esc_attr( $product->get_sku() ),
esc_attr( isset( $class ) ? $class : 'button product_type_external add_to_cart_button' ),
esc_html( $product->add_to_cart_text() )
);
}
return $permalink;
}
}