Related
Here we are talking about selling products (especially pastry or food) in bulk unit / unit / or kg.
All measurements are known weight and quantity,Therefore we must be able to estimate which product in kg will have how many units.
So I created an example of products just to test in woocommerce,
I managed to realize my idea to estimate minimum qty of pieces (or any unit) per kg using a useful piece of code found here.
(1) I put it in a Snippet.
After that I started reading and trying to understand and follow the logic behind the code.
(2) Add some fonctions. just duplicated a few lines.. some copy / paste..
(3) Try to put the same functions in product page (in progress no solution found)
Update 09/12/2019
Code revised no more internal error
// Backend: Add and display a custom field for simple and variable products
add_action( 'woocommerce_product_options_general_product_data', 'add_custom_price_field_to_general_product_data' );
function add_custom_price_field_to_general_product_data() {
global $product_object;
echo '<div class="options_group hide_if_external">';
woocommerce_wp_text_input(array(
'id' => '_min_unit_price',
'label' => __('Min Unit price', 'woocommerce') . ' (' . get_woocommerce_currency_symbol() . ')',
'description' => __('Enter the minimum unit price here.', 'woocommerce'),
'desc_tip' => 'true',
'value' => str_replace('.', ',', $product_object->get_meta('_min_unit_price') ),
'data_type' => 'price'
));
// My custom field "Min price unit prefix"
woocommerce_wp_text_input(array(
'id' => '_min_unit_prefix',
'label' => __('Min Unit prefix', 'woocommerce'),
'description' => __(' Enter prefix unit price here.', 'woocommerce'),
'desc_tip' => 'true',
'value' => str_replace('.', ',', $product_object->get_meta('_min_unit_prefix') ),
'data_type' => 'texte'
));
// My custom field "Estimated quantity"
woocommerce_wp_text_input(array(
'id' => '_estimated_quantity',
'label' => __('Estimated Quantity', 'woocommerce'),
'description' => __('Enter the quantity here.', 'woocommerce'),
'desc_tip' => 'true',
'value' => str_replace('.', ',', $product_object->get_meta('_estimated_quantity') ),
'data_type' => 'price'
));
echo '</div>';
}
// Backend: Save the custom field value for simple and variable products
add_action( 'woocommerce_admin_process_product_object', 'save_product_custom_price_field', 10, 1 );
function save_product_custom_price_field( $product ) {
if ( isset($_POST['_min_unit_price']) ) {
$product->update_meta_data( '_min_unit_price', wc_clean( wp_unslash( str_replace( ',', '.', $_POST['_min_unit_price'] ) ) ) );
}
if ( isset($_POST['_min_unit_prefix']) ) {
$product->update_meta_data( '_min_unit_prefix', wc_clean( wp_unslash( str_replace( ',', '.', $_POST['_min_unit_prefix'] ) ) ) );
}
if ( isset($_POST['_estimated_quantity']) ) {
$product->update_meta_data( '_estimated_quantity', wc_clean( wp_unslash( str_replace( ',', '.', $_POST['_estimated_quantity'] ) ) ) );
}
}
// Frontend variable products: Display the min price with "From" prefix label
add_filter( 'woocommerce_variable_price_html', 'custom_min_unit_variable_price_html', 10, 2 );
function custom_min_unit_variable_price_html( $price, $product ) {
if( $min_unit_price = $product->get_meta('_min_unit_price') ){
$price = wc_price( wc_get_price_to_display( $product, array( 'price' => $min_unit_price ) ) );
$price .= $product->get_meta('_min_unit_prefix');
}
return $price;
}
// Frontend simple products: Display the min price with "From" prefix label
add_filter( 'woocommerce_get_price_html', 'custom_min_unit_product_price_html', 10, 2 );
function custom_min_unit_product_price_html( $price, $product ) {
if( $product->is_type('simple') && $min_unit_price = $product->get_meta('_min_unit_price') ){
$price = wc_price( wc_get_price_to_display( $product, array( 'price' => $min_unit_price ) ) );
$price .= $product->get_meta('_min_unit_prefix');
}
return $price;
}
// Display the cart item weight in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'display_custom_item_data', 10, 2 );
function display_custom_item_data( $cart_item_data, $cart_item ) {
if ( $cart_item['data']->get_weight() > 0 ){
$cart_item_data[] = array(
'name' => __( 'Weight subtotal', 'woocommerce' ),
'value' => ( $cart_item['quantity'] * $cart_item['data']->get_weight() ) . ' ' . get_option('woocommerce_weight_unit')
);
}
// Display the cart item "estimated quantity" in cart and checkout pages
if ( $cart_item['data']->get_meta('_estimated_quantity') ){
$cart_item_data[] = array(
'name' => __( 'Estimated quantity ', 'woocommerce' ),
'value' => ( $cart_item['quantity'] * $cart_item['data']->get_meta('_estimated_quantity') )
);
}
return $cart_item_data;
}
// Save and Display the order item weight (everywhere)
add_action( 'woocommerce_checkout_create_order_line_item', 'display_order_item_data', 20, 4 );
function display_order_item_data( $item, $cart_item_key, $values, $order ) {
if ( $values['data']->get_weight() > 0 ){
$item->update_meta_data( __( 'Weight subtotal', 'woocommerce' ), ( $item['quantity'] * $values['data']->get_weight() ) . ' ' . get_option('woocommerce_weight_unit') );
}
}
Now, I need help to understand how
Estimated quantity: <? Php echo get_post_meta (get_the_ID (), '_estimated_quantity', true); ?>
can Update in real time with the quantity of add_to_cart.
the formula must be extremely simple in jQuery or javascript ?
_estimated_quantity * quantity.
That all I need now. To show to costumer how much they can get piece of cakes (or any others things) in 1 or xx kg
So I put a 15 or xx (approximate value) in backend.
I hope it makes sense for you.
For information I use clean install wordpress + elementor + elementor hello theme + woocommerce.
update 09/12/2019
I corrected the last php error.
I would like to thank Snuwerd for his support and considerable help without him I will not have the courage to throw myself into the world of php code I learned a lot.
Thank you again
Welcome to Stack Overflow!
To answer your questions:
"Verify that the code is valid"
The code looks quite good (especially if this is really your first time messing with PHP)
"and (code) does not create problems in future woocommerce updates."
This question is really hard to answer.
"Now I am trying to put these two lines of information in the product page. via shortcode? or php again ?"
Probably with more filters/actions, like you have done in the current code. And if that doesn't seem possible, maybe by altering/overriding some template(s). Shortcodes don't necessarily make much sense, unless you want to insert the data into content area's in the backend when adding/editing products.
"Also improve the code"
This doesn't seem necessary.
"and add a prefix to Estimated Quantity."
Can you elaborate on what you mean by this?
ps. I am probably off to bed soon, so I'll check again tomorrow.
Update
I send qty and product_id to the server with AJAX and then the server gives back qty * _estimated_quantity;
To get qty from the box on your screen and to set the right value in Estimated quantity, I need you to make a screenshot of their code. Open the page in Google Chrome, right click > inspect element on the quantity box and then make a screenshot of the code in the Elements tab. Also do the same for the Estimated quantity box (that has 15 in it in the screenshot).
I also assume your website is located on the root of your domain. So on www.example.com and not on www.example.com/wordpress/ (The Ajax call needs the right location).
You can add this PHP to your functions.php
<?php
add_action("wp_ajax_product_get_estimated_quantity", "product_get_estimated_quantity"); // calls our function if user is logged in
add_action("wp_ajax_nopriv_product_get_estimated_quantity", "product_get_estimated_quantity"); // calls our function if user is not logged in, we do not do any security checks on which user etc though, but I don't think it's relevant in our case.
function product_get_estimated_quantity () {
error_log('Snuwerd: Ajax call for estimated quantity is being called correctly.');
$product_id = $_REQUEST["product_id"];
if (!is_numeric($product_id)) { // check if really a number, for security purposes
die();
}
$qty = $_REQUEST["qty"];
if (!is_numeric($qty)) { // check if really a number, for security purposes
die();
}
// No need to get product object, can get metadata directly with get_post_meta
// // get estimated_quantity per kg by product_id
// $args = array(
// 'include' => array( $product_id ),
// );
// $products = wc_get_products( $args );
// foreach ($products as $product) {
// }
// echo $product->get_id();
$estimated_quantity_per_kg = get_post_meta( $product_id, '_estimated_quantity', true);
// $estimated_quantity_per_kg = 15; // this line is only for my local testing, since my products dont have _estimated_quantity meta
echo ((int) $estimated_quantity_per_kg) * ((int) $qty);
error_log('Snuwerd: Ajax call for estimated quantity returned to single-product page.');
die();
}
?>
And add this javascript/jquery anywhere you can (assuming that you know how to, its also easy to find out with google (How to add javascript to Wordpress)).
console.log('Snuwerd: Code planted in document.ready');
jQuery(document).ready(function($) {
console.log('Snuwerd: JS code is being loaded.');
if( $('body.single-product').length) { // if on a single product page
console.log('Snuwerd: We are on the single product page');
$( document ).on( 'change', '.quantity input[type=number]', function() { // selector for the qty box is probably already correct
var qty = $( this ).val();
// var product_id = $(this).closest('.product').attr('id');
// product_id = product_id.split('-');
// product_id = product_id[1];
var product_id = get_current_post_id();
console.log('Snuwerd: quantity changed. Sending ajax call with qty'+qty+' and product_id'+product_id);
jQuery.ajax({
type : "post",
dataType : "json",
url : '/wp-admin/admin-ajax.php', // only works if Wordpress is installed in root of your domain. if you installed in www.example.com/wordpress/, then add /wordpress/ before this
data : {action: "product_get_estimated_quantity", product_id : product_id, qty: qty},
success: function(response) {
console.log('Snuwerd: Ajax call returned succesfully');
// right click -> inspect element to find the right selector for estimated quantity (the 15 from your photoshop)
response = parseInt(response);
console.log('Snuwerd: Ajax call returned succesfully with value '+response);
$('#snuwerd > div').html('Estimated quantity: ' + response);
}
});
return false;
});
}
function get_current_post_id() {
var page_body = $('body');
var id = 0;
if(page_body) {
var classList = page_body.attr('class').split(/\s+/);
$.each(classList, function(index, item) {
if (item.indexOf('postid') >= 0) {
var item_arr = item.split('-');
id = item_arr[item_arr.length -1];
return false;
}
});
}
return id;
}
});
In case you want to know how I added the javascript, i made a file in child-theme-directory/js/child.js.
Then added the Jquery to it. And then I added this to functions.php:
function theme_enqueue_child_scripts() {
error_log('Snuwerd: js script being added in theme_enqueue_child_scripts.');
$file = '/js/child.js';
$cache_buster = date("YmdHis", filemtime( get_stylesheet_directory() . $file )); // no uri
wp_enqueue_script( 'child', get_stylesheet_directory_uri() . $file, array( 'jquery' ), $cache_buster, true ); // true = footer
}
add_action( 'wp_enqueue_scripts', 'theme_enqueue_child_scripts' );
Update
I added the selector for the Estimated quantity field in the javascript, and the quantity selector was already correct, so please re-copy the javascript.
I looked at the screenshot where you add in JS and PHP, but the way you add PHP is not good enough for this PHP. Where you add PHP in the screenshot, it only counts for that page and it needs to be sidewide. The Ajax call will not be able to access PHP that is added to a specific page. If Elementor doesn't have a side wide place to add PHP and if you don't want to change the functions.php of your theme, then maybe you can use this plugin: https://wordpress.org/plugins/my-custom-functions/ . Also, don't forget to actually add the PHP I provided, I didn't see it in your JS/PHP screenshot.
Update
I added some debug messages to find out what parts work. Can you enter the PHP code that is meant for functions.php into your site again and also the JS code.
After this open your product page in Google Chrome and press ctrl+shift+i to open developer tools window. Now change the quantity by pressing the arrows in the number box on the page. There should be a few messages in the Console tab in the developer tools window. Can you paste a screenshot of the console here?
If nothing appears in this console, please check that you're not having cache problems > go to Network Tab in developer tools window and check the disable cache checkbox and then refresh the page and try again.
Next, also check the PHP error log, if you don't know how to check it, please learn about PHP error logging here: https://www.loggly.com/ultimate-guide/php-logging-basics/
In the error log search for Snuwerd and show those lines to me as well.
I"m using the tutorial from this blog post to implement Ajax Load More functionality. https://rudrastyh.com/wordpress/load-more-posts-ajax.html
I've successfully implemented this on my archive page for all blog posts. However, I've got several "RElated Posts" sections that use custom WP Queries that I can't get to work. I've tried the solution in this comment: https://rudrastyh.com/wordpress/load-more-posts-ajax.html#comment-1055
It loads new posts, but they are not adhering to the argumenets of the custom query (specifically displaying posts only in the same category).
The custom query is working (it displays 4 related posts from the same category). When i'm loading more, it is not respecting pagination (it's loading 6 posts instead of 4) and it is not respecting the query (it is loading posts not in the same category).
<div class="related-blog-posts gray-bg pt-5 pb-5 blog">
<div class="related-title pb-3">
<h1 class="mb-2">Related Stories</h1>
<img src="/dcustom/wp-content/uploads/2019/04/Path-137#2x.png" />
</div><!-- scroll-down-->
<div class="container">
<div class="row">
<?php
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$query_args = array(
'category__in' => wp_get_post_categories( $post->ID ),
'paged' => $paged,
'post_type' => 'post',
'posts_per_page' => 4,
'post__not_in' => array( $post->ID ),
'orderby' => 'date',
'order' => 'DESC'
);
$third_query = new WP_Query( $query_args ); ?>
<?php
//Loop through posts and display...
if($third_query->have_posts()) : ?>
<?php while ($third_query->have_posts() ) : $third_query->the_post(); ?>
<?php get_template_part('template-parts/content-related-blog-posts'); ?>
<?php endwhile; ?><!-- end the loop-->
<?php endif; ?>
<?php wp_reset_postdata(); ?>
<?php // don't display the button if there are not enough posts
if ( $third_query->max_num_pages > 1 )
echo '<a class="custom_loadmore btn btn-primary">More posts</a>'; // you can use <a> as well
?>
<?php endif; ?><!-- end loop if--->
</div><!-- row -->
</div><!-- container -->
</div><!-- related-case-studies-->
<script>
var test = '<?php echo serialize( $third_query->query_vars ) ?>',
current_page_myajax = 1,
max_page_myajax = <?php echo $third_query->max_num_pages ?>
</script>
<script src="<?php bloginfo('template_url')?>/js/myloadmore.js"></script>
jQuery(function($){ // use jQuery code inside this to avoid "$ is not defined" error
$('.misha_loadmore').click(function(){
var button = $(this),
data = {
'action': 'loadmore',
'query': misha_loadmore_params.posts, // that's how we get params from wp_localize_script() function
'page' : misha_loadmore_params.current_page
};
$.ajax({ // you can also use $.post here
url : misha_loadmore_params.ajaxurl, // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success : function( data ){
if( data ) {
button.text( 'More posts' ).prev().after(data); // insert new posts
misha_loadmore_params.current_page++;
if ( misha_loadmore_params.current_page == misha_loadmore_params.max_page )
button.remove(); // if last page, remove the button
// you can also fire the "post-load" event here if you use a plugin that requires it
// $( document.body ).trigger( 'post-load' );
} else {
button.remove(); // if no data, remove the button as well
}
}
});
});
$('.custom_loadmore').click(function(){
//custom query on front-page.php
var button = $(this),
data = {
'action': 'loadmore',
'query': test,
'page' : current_page_myajax
};
$.ajax({
url : '/dcustom/wp-admin/admin-ajax.php', // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success : function( data ){
if( data ) {
button.text( 'More posts' ).prev().after(data); // insert new posts
current_page_myajax++;
if ( current_page_myajax == max_page_myajax )
button.remove(); // if last page, remove the button
} else {
//button.remove(); // if no data, remove the button as well
}
}
});
});
});
function misha_my_load_more_scripts() {
global $wp_query;
// In most cases it is already included on the page and this line can be removed
wp_enqueue_script('jquery');
// register our main script but do not enqueue it yet
wp_register_script( 'my_loadmore', get_stylesheet_directory_uri() . '/js/myloadmore.js', array('jquery') );
// now the most interesting part
// we have to pass parameters to myloadmore.js script but we can get the parameters values only in PHP
// you can define variables directly in your HTML but I decided that the most proper way is wp_localize_script()
wp_localize_script( 'my_loadmore', 'misha_loadmore_params', array(
'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
'posts' => json_encode( $wp_query->query_vars ), // everything about your loop is here
'current_page' => get_query_var( 'paged' ) ? get_query_var('paged') : 1,
'max_page' => $wp_query->max_num_pages,
) );
wp_enqueue_script( 'my_loadmore' );
}
add_action( 'wp_enqueue_scripts', 'misha_my_load_more_scripts' );
/* AJAX LOOP FOR THE ARCHIVE PAGE */
function misha_loadmore_ajax_handler(){
// prepare our arguments for the query
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded
$args['post_status'] = 'publish';
// it is always better to use WP_Query but not here
query_posts( $args );
if( have_posts() ) :
// run the loop
while( have_posts() ): the_post();
// look into your theme code how the posts are inserted, but you can use your own HTML of course
// do you remember? - my example is adapted for Twenty Seventeen theme
get_template_part( 'template-parts/content-index', get_post_format() );
// for the test purposes comment the line above and uncomment the below one
// the_title();
endwhile;
endif;
die; // here we exit the script and even no wp_reset_query() required!
}
add_action('wp_ajax_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_{action}
add_action('wp_ajax_nopriv_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_nopriv_{action}
I an trying to create a image widget with wp editor. I see the editor but i cant the text like make it bold or bigger nither i see the tab switch from visual to text. Following is my code:
Thanks in advance.
<input type="hidden" id="<?php echo esc_attr($this->get_field_id('description')); ?>" name="<?php echo esc_attr($this->get_field_name('description')); ?>" value="<?php echo esc_attr($instance['description']); ?>" />
<?php
$edi_name = esc_attr($this->get_field_name('description'));
$content = $instance['description'];
$editor_id_new = esc_attr($this->get_field_id('description'));
$settings = array( 'media_buttons' => false,
'textarea_rows' => 6,
'textarea_name' => $edi_name,
'teeny' => false,
'menubar' => false,
'default_editor' => 'tinymce',
'quicktags' => false
);
wp_editor( $content, $editor_id_new, $settings );
?>
<script>
(function($){
tinyMCE.execCommand('mceAddEditor', false, '<?php echo $this->get_field_id('description'); ?>');
})(jQuery);
</script>
Short answer: Because there is a hidden widget where the TinyMCE appears first.
Long answer (sorry, a very long answer):
Go to the Codex and copy the example widget Foo_Widget to make sure we are talking about the same code. Now open your IDE (not an editor) and write a short testing widget as plugin. Starting with a minimal plugin header...
<?php
/*
Plugin Name: Widget Test Plugin
Description: Testing plugincode
*/
... adding the widget code from the codex and registering the widget with the add_action() call. Now modify the form method within the widget class as shown here:
public function form( $instance ) {
if ( isset( $instance[ 'title' ] ) ) {
$title = $instance[ 'title' ];
}
else {
$title = __( 'New title', 'text_domain' );
}
?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
</p>
<?php
/*** add this code ***/
$content = 'Hello World!';
$editor_id = 'widget_editor';
$settings = array(
'media_buttons' => false,
'textarea_rows' => 3,
'teeny' => true,
);
wp_editor( $content, $editor_id, $settings );
/*** end editing ***/
}
Go to your blog, activate the plugin, go to the widget page and drag the Foo Widget into a sidebar. You will see it will fail.
Do you see the Foo Widget description on the left side? Do a right click on the description and choose 'Inspect' from your developer tools (you have some developer tools like FireBug or Chrome DevTools, huh? In FireFox you can also choose the build in 'Inspect Element'). Browse through the HTML code and you will see there is an editor wrap inside the 'hidden' widget.
You can see one editor in the sidebar on the right and there is an editor in the 'hidden' widget on the left. This cannot work properly because TinyMCE don't know which editor should be used.
What do we need?
We need a unique ID for our editor.
/*** add this code ***/
$rand = rand( 0, 999 );
$ed_id = $this->get_field_id( 'wp_editor_' . $rand );
$ed_name = $this->get_field_name( 'wp_editor_' . $rand );
$content = 'Hello World!';
$editor_id = $ed_id;
$settings = array(
'media_buttons' => false,
'textarea_rows' => 3,
'textarea_name' => $ed_name,
'teeny' => true,
);
wp_editor( $content, $editor_id, $settings );
/*** end edit ***/
Modify the code within the form method again with the code above. We create a unique number with rand() and append this number to the id and name attributes. But stop, what about saving the values???
Go to the update method and add die(var_dump($new_instance)); in the first line. If you press Save on the widget, the script will die and print out the submitted values. You will see there is a value like wp_editor_528. If you reload the page and save the widget again, the number will be changed to something else because it is a random number.
How will I know which random number was set in the widget? Simply send the random number with the widget data. Add this to the form method
printf(
'<input type="hidden" id="%s" name="%s" value="%d" />',
$this->get_field_id( 'the_random_number' ),
$this->get_field_name( 'the_random_number' ),
$rand
);
In the update routine, we can now access the random number with $new_instance['the_random_number']; and so we can access the editor content with
$rand = (int) $new_instance['the_random_number'];
$editor_content = $new_instance[ 'wp_editor_' . $rand ];
die(var_dump($editor_content));
As you can see, the editor content will be submitted and you can save it or do anything else with it.
Caveat
The editor content is only submitted correctly if the TinyMCE is not in visual mode (WYSIWYG mode). You have to switch to the text mode befor press 'Save'. Otherwise the predefined content (in this case $content = 'Hello World!';) is submitted. I don't now why, but there is a simple workaround for this.
Write a small jQuery script that triggers the click on the 'text' tab before saving the widget content.
JavaScript (saved as widget_script.js somewhere in your theme/plugin folders):
jQuery(document).ready(
function($) {
$( '.widget-control-save' ).click(
function() {
// grab the ID of the save button
var saveID = $( this ).attr( 'id' );
// grab the 'global' ID
var ID = saveID.replace( /-savewidget/, '' );
// create the ID for the random-number-input with global ID and input-ID
var numberID = ID + '-the_random_number';
// grab the value from input field
var randNum = $( '#'+numberID ).val();
// create the ID for the text tab
var textTab = ID + '-wp_editor_' + randNum + '-html';
// trigger a click
$( '#'+textTab ).trigger( 'click' );
}
);
}
);
And enqueue it
function widget_script(){
global $pagenow;
if ( 'widgets.php' === $pagenow )
wp_enqueue_script( 'widget-script', plugins_url( 'widget_script.js', __FILE__ ), array( 'jquery' ), false, true );
}
add_action( 'admin_init', 'widget_script' );
That's it. Easy, isn't it? ;)
Actual Credit Goes To The Author Of Writting This Test Plugin #Ralf912
Reference URL : Why Can't wp_editor Be Used in a Custom Widget?
I made some improvements to this code in case somebody needs it:
on the form function of the widget I updated the code:
$rand = !empty( $instance['the_random_number']) ? $instance['the_random_number'] : rand( 0, 999 );
$ed_id = $this->get_field_id( 'wp_editor_' . $rand );
$ed_name = $this->get_field_name( 'wp_editor_' . $rand );
$content = !empty( $instance['the_random_number']) ? $instance['wp_editor_' . $rand] : 'Content goes here!';
$editor_id = $ed_id;
$settings = array(
'media_buttons' => true,
'textarea_rows' => 3,
'textarea_name' => $ed_name,
'teeny' => true,
);
wp_editor( $content, $editor_id, $settings ); `
And I also reinitialized the editor because it was broken after save
jQuery(document).on('widget-updated', function(e, widget){
if(widget[0].id.includes("cw_pa_text_widget")) { // if it is the right widget
let editor ="widget-" + widget[0].id.substring(widget[0].id.indexOf('_') + 1);
let randNum = editor + "-the_random_number";
let wpEditorId = editor + "-wp_editor_" + document.getElementById(randNum).value;
var settings = {
quicktags: true,
};
wp.editor.initialize(wpEditorId, settings);
//create the ID for the text tab
var textTab = wpEditorId + '-tmce';
// trigger a click
document.getElementById(textTab).click();
}});
Thank you.
Hi I am trying to add a feature to my store that when someone clicks on a product instead of being redirected to the product page, the product page loads with ajax in the home page like in this website (click on one of the products): http://www.itsjustyes.com. This is my jquery:
jQuery(document).ready(function($){
$('.info_btn').on('click',function(){
var theId = $(this).attr('id');
var div = $('#product-container')
$.post('wp-admin/admin-ajax.php',{
action:'my_get_posts',post_id: theId
}, function(data){
console.log(data);
div.html(data);
})
return false;
});
});
This is my code in functions.php:
//Ajax call to product
function my_get_posts_return()
{
global $post;
$post_id = intval(isset($_POST['post_id']) ? $_POST['post_id'] : 0);
if ($post_id > 0) {
$the_query = new WP_query(array('p' => $post_id));
if ($the_query->have_posts()) {
while ($the_query->have_posts()) : $the_query->the_post();
wc_get_template_part( 'content', 'single-product' );
endwhile;
} else {
echo "There were no posts found";
}
}
wp_die();
}
add_action('wp_ajax_my_get_posts', 'my_get_posts_return');
add_action('wp_ajax_nopriv_my_get_posts', 'my_get_posts_return');
I keep getting that there were no posts found in the loop which is weird cause I know I am sending the right post id. By the way, if I try to get the individual parts of the product page with get_the_title( $post_id ) I get it just fine. It's only when I try to load the template part with the loop that I get this problem. Any idea what I am doing wrong??
Your WP_Query was not finding the correct post type.
$the_query = new WP_query(array('p' => $post_id));
The query above didn't return any post at all. By default, wordpress will assume that you're querying the post_type = 'posts' which is why you cannot find the product post.
Therefore, you need to specify what post_type you're looking for. With WooCommerce product, you can use:
$the_query = new WP_query(array('p' => $post_id, 'post_type' => 'product'));
P.S. It's a good practice to use wp_localize_script function to register your ajaxurl, rather than hard coded in your javascript. You can follow this post for more detail.
Hope this helps.
I have researched several similar questions on stackoverflow about this topic that already have answers.
Some of the answers don't seem to fully work and some are just over my head.
I have been reading and reworking my code for over a week so I though I would try asking again with more detail than the other questions had.
I've written a very simple WordPress plugin that's only purpose in life is to load a fully functional editor via ajax.
Here is a screencast of this plugin working (with errors):
http://screencast.com/t/eyrTdbUy
I think that if my question can be answered it will help a lot of people.
Here is exactly what the plugin does.
It loads my custom page template instead of the theme template. In this template there is a editor created with the wp_editor function (to load the required files) and a link to add a new editor.
When you click the "add editor" link a new editor is created using the wp_editor function via ajax then initialized with javascript and new link is added to add another.
This only works if a user is logged in.
I wouldn't advise installing this on your active website because it will take over your pages. This plugin is for example only so it should only be installed on tester sites.
Here's the problems...
The first instance of the ajax loaded editor works but there is the following errors when you click the tabs to switch back and forth from visual to text
"TypeError: e is undefined"
"TypeError: c is undefined"
The "TypeError: e is undefined" also happens when the first new editor is loaded.
After the first instance is loaded another editor cannot be added.
So my question is... What is wrong with my code?
The plugin is made up of 4 files.
File 1 is the plugin file "load_editor.php" (it just includes the functions):
include('functions.php');
File 2 is the functions file "functions.php":
<?
// load custom editor template
function load_editor_template( $template )
{
$template = plugin_dir_path( __FILE__ ) . 'template.php';
return $template;
}
add_filter( 'template_include', 'load_editor_template' );
// load javascript
function load_editor_scripts() {
wp_enqueue_script( 'load_editor', plugins_url() . '/load_editor/js/load_editor.js', array(), '', true );
wp_enqueue_script( 'jquery');
}
add_action( 'wp_enqueue_scripts', 'load_editor_scripts' );
// create new editor
function load_editor_new_editor() {
$id = $_POST['id'];
$number = $_POST['number'];
$next = $number + 1;
$full_id = $id.$number;
echo "<h1>Editor $number</h1>";
$content = '<p>This is example content.</p>';
wp_editor($content, $full_id, array('textarea_rows' => 3));
// initiate new editor
echo "<script>
tinyMCE.execCommand('mceAddEditor', true, $full_id);
tinyMCE.init(tinyMCEPreInit.mceInit[$full_id]);
</script>";
// create "add new" text
echo "<div><a onclick=\"load_new_editor('editor', $next);\" href='javascript:void(0);'>Click here</a> to add another editor</div>";
die();
}
add_action( 'wp_ajax_load_editor_new_editor', 'load_editor_new_editor' );
File 3 is the template file "template.php" :
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Load Editor</title>
<?php wp_head(); ?>
</head>
<body>
<? wp_editor('Ecample content', 'id', array('textarea_rows' => 3)); ?>
<div id="add"><a onClick="load_new_editor('editor', 1);" href="javascript:void(0);">Click here</a> to add an editor</div>
<div id="editor_container">
<!-- Editors will load here -->
</div>
<script>
<?
echo 'ajaxurl = "'.admin_url('admin-ajax.php').'";';
?>
</script>
<?php wp_footer(); ?>
</body>
</html>
And file 4 is the javascript file "load_editor.js":
function load_new_editor(id, number){
// remove click to add
jQuery('#add').remove();
var fullId = id + number;
var data = {
'action': 'load_editor_new_editor',
'number': number,
'id': id
};
jQuery.post(ajaxurl, data, function(response) {
//add new editor
jQuery('#editor_container').append(response);
});
}
I've also put it on github here:
enter link description here
Thank you so much for any help that you can give. I've been trying to get this to work for so long it's frying my brain. I even hired a programmer via elance and he was unable to get as far as I did.
This is the best I can come up with and I think it is good enough for me.
Everything is working except the quicktags and I can live without them.
I removed the javascript from funtions.php
<?
// load custom editor template
function load_editor_template( $template )
{
$template = plugin_dir_path( __FILE__ ) . 'template.php';
return $template;
}
add_filter( 'template_include', 'load_editor_template' );
// load javascript
function load_editor_scripts() {
wp_enqueue_script( 'load_editor', plugins_url() . '/load_editor/js/load_editor.js', array(), '', true );
wp_enqueue_script( 'jquery');
}
add_action( 'wp_enqueue_scripts', 'load_editor_scripts' );
// create new editor
function load_editor_new_editor() {
$id = $_POST['id'];
$number = $_POST['number'];
$next = $number + 1;
$full_id = $id.$number;
echo "<h1>Editor $number</h1>";
$content = '<p>This is example content.</p>';
wp_editor($content, $full_id, array('textarea_rows' => 3));
// create "add new" text
echo "<div id='add'><a onclick=\"load_new_editor('editor', $next);\" href='javascript:void(0);'>Click here</a> to add another editor</div>";
die();
}
add_action( 'wp_ajax_load_editor_new_editor', 'load_editor_new_editor' );
Then I changed the following on load_editor.js
Added the quicktags function to get the tabs to work without error
Called tinymce.init with the settings that WordPress uses
I think that's it.
// JavaScript Document
function load_new_editor(id, number){
// remove click to add
jQuery('#add').remove();
var fullId = id + number;
var data = {
'action': 'load_editor_new_editor',
'number': number,
'id': id
};
jQuery.post(ajaxurl, data, function(response) {
//add new editor
jQuery('#editor_container').append(response);
// this is need for the tabs to work
quicktags({id : fullId});
// use wordpress settings
tinymce.init({
selector: fullId,
theme:"modern",
skin:"lightgray",
language:"en",
formats:{
alignleft: [
{selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'left'}},
{selector: 'img,table,dl.wp-caption', classes: 'alignleft'}
],
aligncenter: [
{selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'center'}},
{selector: 'img,table,dl.wp-caption', classes: 'aligncenter'}
],
alignright: [
{selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'right'}},
{selector: 'img,table,dl.wp-caption', classes: 'alignright'}
],
strikethrough: {inline: 'del'}
},
relative_urls:false,
remove_script_host:false,
convert_urls:false,
browser_spellcheck:true,
fix_list_elements:true,
entities:"38,amp,60,lt,62,gt",
entity_encoding:"raw",
keep_styles:false,
paste_webkit_styles:"font-weight font-style color",
preview_styles:"font-family font-size font-weight font-style text-decoration text-transform",
wpeditimage_disable_captions:false,
wpeditimage_html5_captions:true,
plugins:"charmap,hr,media,paste,tabfocus,textcolor,fullscreen,wordpress,wpeditimage,wpgallery,wplink,wpdialogs,wpview",
selector:"#" + fullId,
resize:"vertical",
menubar:false,
wpautop:true,
indent:false,
toolbar1:"bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_more,spellchecker,fullscreen,wp_adv",toolbar2:"formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help",
toolbar3:"",
toolbar4:"",
tabfocus_elements:":prev,:next",
body_class:"id post-type-post post-status-publish post-format-standard",
});
// this is needed for the editor to initiate
tinyMCE.execCommand('mceAddEditor', false, fullId);
});
}
Here is a screencast of it working.
http://screencast.com/t/Psd9IVVY
If anyone knows how to get the quicktags to show, I would love to know.
Also, if you spot something wrong with my code let me know.
I have updated the github if you want to download it here:
https://github.com/ccbgs/load_editor
( Answer found here: https://wordpress.stackexchange.com/questions/51776/how-to-load-wp-editor-through-ajax-jquery/192132 )
1) in functions.php,add:
add_action('init','my_wpEditOUPUTT'); function my_wpEditOUPUTT(){
if (isset($_POST['Give_me_editorrr'])){
wp_editor( '' , 'txtrID_'.$_POST['myNumber'], $settings = array( 'editor_class'=>'my_class', 'textarea_name'=>'named_'. $_POST['myNumber'], 'tinymce'=>true , 'media_buttons' => true , 'teeny' => false,));
exit;
}
}
2) inside dashboard HTML page:
<div id="MyPlace"></div> Click to load
<script type="text/javascript">
startNumber = 1;
function myLoad(){ alert('wait 1 sec');
startNumber ++;
jQuery.post('./index.php', '&Give_me_editorrr=1&myNumber='+startNumber ,
function(data,status){
if (status == "success") {
document.getElementById('MyPlace').innerHTML += data; alert("Inserted!");
tinymce.init({ selector: 'txtrID_'+startNumber, theme:'modern', skin:'lightgray'}); tinyMCE.execCommand('mceAddEditor', false, 'txtrID_'+startNumber);
}
});
}
</script>