Woocommerce error after loading variation items with ajax in archive page - wordpress

im using the archive pages of the shop to navigate for every product using ajax, after i load the product and show it i reload the add-to-cart-variation.min.js and it seems to work but when i choose a variation i get an error in console.
My script is:
js
jQuery.ajax({
type: "post",
url: ajax_var.url,
data: "action=" + ajax_var.action + "&nonce=" + ajax_var.nonce + "&id=" + id,
success: function(result){
jQuery('#mk-archive-products').append('<div id="resultado-ajax">'+result+'</div>');
},
complete: function(){
loadVariationScript();
},
});
function loadVariationScript() {
jQuery.getScript("/wp-content/plugins/woocommerce/assets/js/frontend/add-to-cart-variation.min.js");
jQuery('.variations_form').each(function () {
jQuery(this).wc_variation_form();
});
}
php:
function my_event_list_cb() {
$nonce = sanitize_text_field( $_POST['nonce'] );
$product_id = sanitize_text_field( $_POST['id'] );
if ( ! wp_verify_nonce( $nonce, 'my-ajax-nonce' ) ) {
die ( 'Busted!');
}
$args = array(
'post_type' => 'product',
'posts_per_page' => 1,
'post__in'=> array($product_id)
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
while ($query->have_posts()) {
$query->the_post();
wc_get_template_part( 'content', 'single-product' );
}
}
wp_die();
}
The error i get in console when i chose a variation is:
Uncaught TypeError: e.getElementById(...) is null
jQuery 22
m
onFoundVariation
dispatch
handle
trigger
trigger
trigger
each
each
trigger
onFindVariation
dispatch
handle
trigger
trigger
trigger
each
each
trigger
onChange
dispatch
handle
jquery.js line 2 > eval:1:13099
jQuery 22
m
onFoundVariation
dispatch
handle
trigger
trigger
trigger
each
each
trigger
onFindVariation
dispatch
handle
trigger
trigger
trigger
each
each
trigger
onChange
dispatch
handle
receiveMessage resource://gre/actors/SelectChild.jsm:268
receiveMessage resource://gre/actors/SelectChild.jsm:465
Anybody knows a way to get the products in this archive page and make that the variation form works?
Thx in advance

Related

Woocommerce ajax call on single product page

I get all my products from an API and those who are variations to each other all share a custom meta key called "api_product_family". The products with the same api_product_family are variants to each other, so on the single page I have a hook where I display the other variants with image and anchor to it's variants.
My code:
function mv_variations() {
global $post;
global $wpdb;
$product_id = $post->ID;
$product_family = get_post_meta( $post->ID, 'api_product_family', true );
if(!empty($product_family)) {
$query = "
SELECT post_id
FROM " . $wpdb->prefix . "postmeta
WHERE meta_value = '" . $product_family . "'
";
$products = $wpdb->get_col($query);
if(count($products) > 0) {
for($i=0; $i<count($products); $i++) {
if($products[$i] == $product_id) {
unset($products[$i]);
}
}
if(count($products) > 0) {
print '<h3>Choose other variants: </h3>';
foreach($products as $product) {
$image = wp_get_attachment_image_src(get_post_thumbnail_id($product));
print '<img src="' . $image[0] . '" alt="img"/> ';
}
}
}
}
}
add_action( 'woocommerce_single_product_summary', 'mv_variations' );
The problem:
I have a LOT of posts, and a lot of post_meta's, so it's taking an eternity to load so I was thinking to move this whole function inside and AJAX call so it's doesn't slow down the initial load. The problem is that I have no idea how to do that with wordpress
Are you simply looking to run a WP function via AJAX?
1) Add ajax actions
This needs to run inside the main plugin file. If you run this only on the public code, it will not work. WP is a little weird and all ajax uses admin-ajax.php
if ( wp_doing_ajax() ){
add_action( 'wp_ajax_yourcustomfunction', array($this, 'yourcustomfunction') );
add_action( 'wp_ajax_nopriv_yourcustomfunction', array($this, 'yourcustomfunction') );
}
function yourcustomfunction(){
echo 'success';
exit();
}
2) In JavaScript
in the backend, you have the global: ajaxurl for the ajax url
BUT in the front end you need to pass this as a variable via wp_localize_script
$datatoBePassed = array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
);
wp_localize_script( 'your_javascript_script', 'plugin_display_settings', $datatoBePassed );
In JS:
var datavar = {
action: 'yourcustomfunction',
};
$.post(plugin_display_settings.ajaxurl, datavar, function(response){
//response received here. It will be 'success' which is echoed in PHP
});
3)
If you also want to run a security nonce check (to check the request truly originates from the WP website, prevents some attacks), it gets a little more complicated:
$datatoBePassed should also include 'security' => wp_create_nonce( 'yourplugin_security_nonce' ),
datavar in JS includes security: plugin_display_settings.security,
Finally, your PHP custom function begins with:
// Check security nonce.
if ( ! check_ajax_referer( 'yourplugin_security_nonce', 'security' ) ) {
wp_send_json_error( 'Invalid security token sent.' );
wp_die();
}
// If security check passed, run further
So I think you might get better performance using WP_Query. Below I converted what you have into a custom WP_Query. May need some slight adjustment but should be the right direction.
function mv_variations() {
global $post_id;
// get current post "product family"
$product_family = get_post_meta( $post_id, 'api_product_family', true );
// build related "product family" products query
$products_query_args = array(
'post_type' => 'product', // may need to update this for your case
'posts_per_page' => -1, // return all found
'post__not_in' => array($post_id), // exclude current post
'post_status' => 'publish',
// use a meta query to pull only posts with same "product family" as current post
'meta_query' => array(
array(
'key' => 'api_product_family',
'value' => $product_family,
'compare' => '='
)
)
);
$products_query = new WP_Query($products_query);
// use "the loop" to display your products
if ( $products_query->have_posts() ) :
print '<h3>Choose other variants: </h3>';
while ( $products_query->have_posts() ) : $products_query->the_post();
print ''. wp_get_attachment_image() .'';
endwhile;
// restore global post
wp_reset_postdata();
endif;
}
add_action( 'woocommerce_single_product_summary', 'mv_variations' );

WordPress Update custom post status by clicking custom link in admin

i have a site where i get posts from users, those posts save in WP as a custom post with status pending,
Admin have custom link in that custom post type page Approve | Reject
Approve should change post status to Public
Reject Should change post status to trash/del
can anyone tell any hook to anything which i can run to change post status from backend by clicking these custom links
the code of approve | reject button if anyone want to see
add_filter( 'manage_dream_posts_columns', 'smashing_filter_posts_columns' );
function smashing_filter_posts_columns( $columns ) {
$columns['decision'] = __( 'Decision Pending', 'rima' );
return $columns;
}
add_action( 'manage_dream_posts_custom_column', 'smashing_dream_column', 10, 2);
function smashing_dream_column( $column, $post_id ) {
if ( 'decision' === $column ) {
if (get_post_status ( $post_id ) == 'pending') {
echo '<div class="decision">ApproveReject</div>';
}
else {
echo '<div class="decision"><span class="dapprove">Approved</span></div>';
}
}
}
You could do something like this - it's a bit hacky and uses jQuery but is a quick fix for your issue using an Ajax method so it all works realtime with your admin screen. You can approve/reject multiple posts without any page reloads, including some colour feedback to let you know what's happening.
You need to add 2 new actions:
add_action( 'wp_ajax_set_post_status', 'set_post_status_ajax_handler' );
add_action( 'admin_footer', 'set_post_status_js' );
Then add these functions:
function set_post_status_js()
{
$nonce = wp_create_nonce('set_post_status');
$ajax_url = admin_url('admin-ajax.php'); ?>
<script type="text/javascript">
(function($){
$(document).ready(function(){
$('.decision a').click(function(event){
event.preventDefault();
$.post( "<?= $ajax_url; ?>", {
nonce: "<?= $nonce; ?>",
action: 'set_post_status',
post_id: $(this).data('post_id'),
status: $(this).data('status'),
}, function(data){
if (data.ok) {
var postStateLabel = (data.status === 'publish') ? '<span style="color: #009900;">Approved</span>' : '<span style="color: #990000;">Rejected</span>';
$('#post-' + data.id)
.css('background', data.status === 'publish' ? '#EEFFEE' : '#FFEEEE')
.find('.post-state').html( postStateLabel );
}
});
});
});
})(jQuery)
</script>
<?php
}
And
function set_post_status_ajax_handler()
{
$nonce = $_POST['nonce'];
if ( ! wp_verify_nonce( $nonce, 'set_post_status' ) )
die ( 'Not permitted');
// Extract the vars from the Ajax request
$post_id = $_POST['post_id'];
$status = $_POST['status'];
// Now update the relevant post
$post_id = wp_update_post([
'ID' => $post_id,
'post_status' => $status,
], true);
// make sure it all went OK
if (is_wp_error($post_id))
{
$response = [
'ok' => false,
];
} else
{
$response = [
'ok' => true,
'id' => $post_id,
'status' => $status,
];
}
// Return the response
wp_send_json( $response );
}
Finally, you need to change your Approve / Reject links to this HTML:
echo '
<div class="decision">
Approve
Reject
</div>';
Hopefully that will get you sorted. Cheers.

Wordpress custom button/action custom post type

I have a custom post type called request created with Toolset plugin.
I need to add a button in these admin pages (only for this custom post type):
new request (post-new.php)
edit request (post.php)
When admin submit the button I need to send an email (no problem for this) with info about the post.
How can I add the button and a callback to submit?
One way to add new elements to the Post Edit screen is via metaboxes.
Please check the following code:
/**
* Adds a call-to-action metabox to the right side of the screen under the "Publish" box.
*/
function wp645397_add_cta_metabox() {
add_meta_box(
'wp645397_request_cta',
'Call-to-action title here', /* This is the title of the metabox */
'wp645397_request_cta_html',
'request', /* the request post type */
'side',
'high'
);
}
add_action( 'add_meta_boxes', 'wp645397_add_cta_metabox' );
/**
* Output the HTML for the call-to-action metabox.
*/
function wp645397_request_cta_html() {
global $post;
// Nonce field to validate form request came from current site
wp_nonce_field( 'request_send_post_details', 'request_cta_nonce' );
// Output the call-to-action button
?>
Call-to-action button text here
<script>
/**
* We'll handle the button via Ajax to avoid having to reload the screen.
*/
jQuery(function($){
// Handle button click
$( "#wp645397_request_cta #btn-call-to-action" ).on("click", function(e){
e.preventDefault();
// Get the security nonce
var nonce = $(this).parent().find("#request_cta_nonce").val();
// Send the data via AJAX
$.post(
ajaxurl,
{
action: 'send_request_email',
nonce: nonce,
postid: <?php echo $post->ID; ?>
},
function( response ){
// Do something after the data has been sent
if ( 'OK' == response ) {
alert( 'Info sent' );
}
else {
alert( 'Something went wrong, try again' );
}
}
);
});
});
</script>
<?php
}
/**
* Handles CTA AJAX.
*/
function wp645397_send_request_email(){
// Invalid nonce
if ( !isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'request_send_post_details' ) ) {
wp_die( 'error' );
}
$post_ID = $_POST['postid'];
// Get post data
$post = get_post( $post_ID );
// Get post title
$post_title = $post->post_title;
// Get custom field, etc
// #TODO
// Send e-mail with data
// #TODO
wp_die('OK');
}
add_action( 'wp_ajax_send_request_email', 'wp645397_send_request_email' );
What it does:
Adds a custom metabox right above the Publish box on the right.
When the user clicks on the "Call-to-action button text here" button (remember to rename it!), it'll send the ID of the current post (request) via Ajax to a function called wp645397_send_request_email, where you need to process the data and send the e-mail.
I added some comments in the code that should explain what's going on. If you have any questions don't hesitate to ask, ok?
I am not sure what options toolset plugin provides but if I were to do this programatically, I would do something like
$post_types = array('post', 'page');
$args = array(
'public' => true,
'_builtin' => false,
);
$output = 'names'; // names or objects, note names is the default
$operator = 'and'; // 'and' or 'or'
$fetch_post_types = get_post_types($args, $output, $operator);
foreach ($fetch_post_types as $key => $value) {
if ($value != 'vocabulary' && $value != 'augmentation') {
array_push($post_types, $value);
}
}
add_meta_box('email_sender_post_type_metabox', __('Email Options', 'seoaipdl'), 'email_sender_post_type_metabox', $post_types, 'side', 'high', null);
function email_sender_post_type_metabox() {
//Button HTML code here
}
add_action('save_post', 'save_meta_data_function', 10, 2);
function save_meta_data_function($id, $data) {
if (!current_user_can("edit_post", $id)) {
return $data;
}
if (defined("DOING_AUTOSAVE") && DOING_AUTOSAVE) {
return $data;
}
\\$_POST variable will have your submit button here.
}
Alternatively You can add a button using jquery and trigger your email function using ajax on this button click.
To do so you will need to look into admin_enqueue_script and wp_localize_script

Inserting checkbox values into WordPress database

I am trying to insert the values of all ticked checkboxes in a wordpress database, into a table which i created myself. Here's my jQuery code:
$(document).ready(function(){
$('#submit').click(function(){
var insert = [];
$('.get_value').each(function(){
if($(this).is(":checked") ){
insert.push($(this).val() );
}
});
insert = insert.toString();
$.ajax({
url:"insert.php",
method:"POST",
data:{insert:insert},
success:function(data){
$('.result').html(data);
}
});
});
});
and my insert code, (its in insert.php):
if ( isset($_POST["insert"]) ){
global $wpdb;
$table_name = $wpdb->prefix . "status";
$wpdb->insert($table_name, array(
'status' => 'approved'
);
}
its not showing any errors, but its not inserting either.I dont know if this information is useful, but the checkboxes are at the admin backend as part of a custom post type.
This isn't going to work, because you are calling insert.php in your ajax call. The url should point to ajaxurl that is localized with the script where your ajax is.
So if your script is located in file called custom.js and you have it enqueued it like:
wp_enqueue_script( 'my_custom_script', get_template_directory_uri() . '/js/custom.js', array( 'jquery' ),'', true );
Then you'll localize your ajax url like
wp_localize_script( 'my_custom_script', 'ajax_call', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
) );
And use it in your script like
$(document).ready(function(){
$('#submit').click(function(){
var insert = [];
$('.get_value').each(function(){
if($(this).is(":checked") ){
insert.push($(this).val() );
}
});
insert = insert.toString();
$.ajax({
url: ajax_call.ajaxurl,
method:"POST",
data:{
'action': 'my_action_callback',
'insert': insert,
},
success:function(data){
$('.result').html(data);
}
});
});
});
Also your insert.php code should be inside a function hooked on wp_ajax hooks
add_action( 'wp_ajax_my_action_callback', 'my_action_callback' );
add_action( 'wp_ajax_nopriv_my_action_callback', 'my_action_callback' );
function my_action_callback(){
if ( isset($_POST["insert"]) ){
global $wpdb;
$table_name = $wpdb->prefix . "status";
$wpdb->insert($table_name, array(
'status' => 'approved'
);
}
}
https://codex.wordpress.org/AJAX_in_Plugins

AJAX Click Counter Wordpress

I need a simple click counter for links in my wordpress posts. I used google a lot but couldnt find a working one. I want to count clicks from a specific class and store it in post_meta or as a custom field to display the count later.
here is some code i found but i cant get it to work..nothting happens when i click the link.
js
jQuery(document).ready(function($) {
$("a[link-out]").click(function() {
var linkout = $(this).attr("link-out");
var data = {
action: 'my_action',
postid: linkout
};
$.post(MyAjax.ajaxurl, data);
});
});
php
wp_enqueue_script( 'my-ajax-request', plugin_dir_url( __FILE__ ) . 'js/countclicks.js', array( 'jquery' ) );
// declare the URL to the file that handles the AJAX request (wp-admin/admin-ajax.php)
wp_localize_script( 'my-ajax-request', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
add_action('wp_ajax_my_action', 'my_action_callback');
add_action('wp_ajax_nopriv_my_action', 'my_action_callback');
function my_action_callback() {
global $wpdb;
$post_id = $_POST['postid'];
$post_id = mysql_real_escape_string($post_id);
$wpdb->query("UPDATE wp_postmeta SET meta_value = meta_value+1 WHERE post_id = '$post_id' AND meta_key = 'clicks_out'");
}
here is another one i found here on stackoverflow, but also doenst work
coding ajax click counter on wordpress

Resources