Adding wp_editor inside a thickbox - ajax

I would like to add a wp_editor inside a modal dialog (thickbox) at frontend but only gets an empty editor with no buttons on in. (WordPress 3.5 and plugin development)
The wp_editor is attached via an ajax call...
It seems like some important javascripts is missing to the page.
Is it possible to preload editor scripts i WP in some way?
Here is a sample plugin to expose the problem (adds a edit link to every content):
<?php
/*
Plugin Name: ThickboxEditor
*/
$thickboxeditor = new ThickboxEditor();
class ThickboxEditor{
function __construct()
{
add_action( 'wp_print_styles', array( &$this, 'wp_print_styles' ) );
add_action( 'init', array( &$this, 'init' ) );
add_filter( 'the_content', array( &$this, 'the_content' ) );
add_action( 'wp_ajax_thickboxeditor', array( &$this, 'editor' ) );
add_action( 'wp_ajax_nopriv_thickboxeditor', array( &$this, 'editor' ) );
}
function the_content( $content ){
$content .= 'EDIT THICKBOXEDITOR';
return $content;
}
function editor(){
wp_editor( $this->postcontent, 'postcontent', array(
'media_buttons' => false,
'teeny' => false,
'textarea_rows' => '7',
'tinymce' => array( 'plugins' => 'inlinepopups, fullscreen, wordpress, wplink, wpdialogs' )
) );
die(0);
}
}
?>
UPDATE
Thanks to #danielauener one solution is to initialize mceAddControl. So here is a working sample of the same plugin:
<?php
/*
Plugin Name: ThickboxEditor
*/
$thickboxeditor = new ThickboxEditor();
class ThickboxEditor{
function __construct()
{
add_action( 'wp_print_styles', array( &$this, 'wp_print_styles' ) );
add_action( 'init', array( &$this, 'init' ) );
add_filter( 'the_content', array( &$this, 'the_content' ) );
add_action( 'wp_ajax_thickboxeditor', array( &$this, 'editor' ) );
add_action( 'wp_ajax_nopriv_thickboxeditor', array( &$this, 'editor' ) );
add_action( 'wp_footer', array( &$this, 'wp_footer' ) );
}
function wp_footer(){
echo '<!--';
wp_editor( '', 'invisible_editor_for_initialization' );
echo '-->';
}
function the_content( $content ){
$content .= 'EDIT THICKBOXEDITOR';
return $content;
}
function editor(){
wp_editor( '', 'postcontent', array(
'media_buttons' => false,
'teeny' => false,
'textarea_rows' => '7',
'tinymce' => array( 'plugins' => 'inlinepopups, fullscreen, wordpress, wplink, wpdialogs' )
) );
?>
<script language="javascript">
jQuery(document).ready(function(){
tinymce.execCommand('mceAddControl',true,'postcontent');
});
</script>
<?php
die(0);
}
}
?>
It would be really nice to skip the ugly wp_editor initialization :-)

Funny, that thickbox doesn't provides any callbacks. But as I mentioned on twitter, I would try a $.ajaxSuccess call to solve the ugly js-inject. Just add the following to one of your javascript files:
(function($) {
// gets called for every successful ajax call
$(document).ajaxSuccess( function(evt, request, settings) {
// make sure this call was from your thickbox
if ($('#your-thickbox-selector').length > 0) {
tinymce.execCommand('mceAddControl',true,'postcontent');
}
});
})( jQuery );
UPDATE: The ajaxSuccess method has to be assigned to an element, changed the code

Related

Wordpress Ajax returning full html of same page

Am trying to run Ajax call in my Woocommerce checkout page, but am always getting the full html of same page return.
add_action( 'wp_enqueue_scripts', 'theme_scripts' );
function theme_scripts() {
wp_enqueue_script( 'theme_scripts', get_stylesheet_directory_uri() . '/assets/js/theme.js', array(), '1.0.0', true );
wp_localize_script( 'theme_scripts', 'my_ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
}
Am calling the ajax when address is changed
add_action('wp_footer','my_custom_ajax');
function my_custom_ajax(){
?>
<script>
(function($){
$( document.body ).on( 'updated_checkout', function(){
$.ajax({
url: my_ajax_object.ajaxurl,
data: {
'action':'example_ajax_request',
},
success:function(data) {
console.log(data);
},
error: function(errorThrown){
console.log(errorThrown);
}
});
});
})(jQuery);
</script>
<?php
}
The example Function
function example_ajax_request() {
echo 'ok';
wp_send_json_success( 'It works' );
die();
}
add_action( 'wp_ajax_example_ajax_request', 'example_ajax_request' );
add_action( 'wp_ajax_nopriv_example_ajax_request', 'example_ajax_request' );
Fixed by using 'nonce'
refer to this sample project

How to set an ajax url in wordpress? I want to call it with datatables.net in server side processing mode

I want to set up an ajax url to use it with Datatables in wordpress. But I don't know how I would set up the corresponding url in wordpress. I guess its a rather easy task but don't know how to do it.
I found example code how to set up datatables server side processing in wordpress but I am struggling to put the following code in real life (how to create the corresponding FrontendConfig.ajaxurl in Wordpress? Or would it be better to create a wordpress json endpoint?)
jQuery
jQuery('#student_table').DataTable({
"bProcessing": true,
"serverSide": true,
"ajax":{
"url": FrontendConfig.ajaxurl+'?action=getStudentsFromExamIdAjax&exam_nounce=exam_nounce_data&exam_id=1',
type: "post",
}
});
Wordpress php
add_action('wp_ajax_getStudentsFromExamIdAjax', 'getStudentsFromExamIdAjax' );
add_action('wp_ajax_nopriv_getStudentsFromExamIdAjax', 'getStudentsFromExamIdAjax' );
function getStudentsFromExamIdAjax(){
if(empty($_GET['action']) || empty($_GET['exam_id'])){
wp_send_json_error( new \WP_Error( 'Bad Request' ) );
}
if(isset($_GET['exam_id']) && $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( $_GET['exam_nounce'], 'exam_nounce_data' )):
$exam_id = (isset($_GET['exam_id'])) ? absint($_GET['exam_id']) : '';
/*# You can create a function to get the data here */
$students = getStudentsFromExamId($exam_id);
$tdata = [];
foreach ($students as $key => $value):
$tdata[$key][] = $value->roll_no;
$tdata[$key][] = $value->name;
$tdata[$key][] = $value->phone;
$tdata[$key][] = 'action here';
endforeach;
$total_records = count($tdata);
$json_data = array(
/* $_REQUEST['draw'] comes from the datatable, you can print to ensure that */
"draw" => intval( $_REQUEST['draw'] ),
"recordsTotal" => intval( $total_records ),
"recordsFiltered" => intval( $total_records ),
"data" => $tdata
);
echo json_encode($json_data);
endif;
wp_die();
}
You just need to set the following enqueue_style_and_scripts into your function.php file. You need to set wp_localize_script, check this link https://developer.wordpress.org/reference/functions/wp_localize_script/. Don't forget to change the code as per your coding requirement.
/*# Enqueue styles & scripts */
if( !function_exists('enqueue_style_and_scripts') ):
function enqueue_style_and_scripts(){
$version = wp_get_theme()->get('Version');
wp_enqueue_script(
'general_js',
get_stylesheet_directory_uri() . '/assets/js/general.js',
array('jquery'),
$version,
true
);
$frontendconfig = array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'is_user_logged_in' => is_user_logged_in(),
);
wp_localize_script( 'general_js', 'FrontendConfig', $frontendconfig );
}
add_action('wp_enqueue_scripts', 'enqueue_style_and_scripts');
endif;

Wordpress Lazy Loading using Pagination

im doing a lazy loading with WP_Query Pagination
it's working fine but the content duplicate itself when it reaches it's end
and when i search for a specific result it shows the result correctly
but after that it still want to do lazy load so it load random data
here is my code
lazy-load.php
<?php
add_action('wp_ajax_nopriv_load_posts_by_ajax', 'load_posts_by_ajax_callback');
add_action('wp_ajax_load_posts_by_ajax', 'load_posts_by_ajax_callback');
function load_posts_by_ajax_callback(){
// check_ajax_referer( 'load_more_posts', 'security' );
$paged = $_POST['page'];
$args = array(
'post_type' => 'unit',
'post_status' => 'publish',
'posts_per_page' => 4,
'paged' => $paged
);
if ( !empty($_POST['taxonomy']) && !empty($_POST['term_id']) ){
$args['tax_query'] = array (
array(
'taxonomy' => $_POST['taxonomy'],
'terms' => $_POST['term_id'],
),
);
}
if ( ! is_null($_POST['offer']) ) {
$args['meta_query'][] = array(
'key' => 'WAKEB_hot',
'value' => '1',
'compare' => '=',
);
}
if ( ! is_null($_POST['purpose']) ) {
$args['meta_query'][] = array(
'key' => 'WAKEB_vacation',
'value' => '1',
'compare' => '=',
);
}
if (!empty($_POST['project'])){
$args['meta_query'] = array (
array(
'key' => 'WAKEB_project',
'value' => $_POST['project'],
'compare' => '='
),
);
}
// start buffer
ob_start();
$query = new WP_Query( $args );
if ( $query->have_posts() ) :
while($query->have_posts()){ $query->the_post();
get_template_part("template-parts/units");
}
endif; wp_reset_postdata();
// start buffered data in data variable
$data = ob_get_clean();
wp_send_json_success( $data );
wp_die();
}
add_action('wp_ajax_nopriv_load_projects_by_ajax', 'load_projects_by_ajax_callback');
add_action('wp_ajax_load_projects_by_ajax', 'load_projects_by_ajax_callback');
function load_projects_by_ajax_callback(){
// check_ajax_referer( 'load_more_posts', 'security' );
$paged = $_POST['page'];
$args = array(
'post_type' => 'project',
'post_status' => 'publish',
'posts_per_page' => 4,
'paged' => $paged
);
if ( ! is_null($_POST['ptype']) ) {
$args['tax_query'] = array (
array(
'taxonomy' => 'pptypes',
'field' => 'slug',
'terms' => $_POST['ptype'],
),
);
}
if ( !empty($_POST['taxonomy']) && !empty($_POST['term_id']) ){
$args['tax_query'] = array (
array(
'taxonomy' => $_POST['taxonomy'],
'terms' => $_POST['term_id'],
),
);
}
// start buffer
ob_start();
$query = new WP_Query( $args );
if ( $query->have_posts() ) :
while($query->have_posts()){ $query->the_post();
get_template_part("template-parts/projects");
}
endif; wp_reset_postdata();
// start buffered data in data variable
$data = ob_get_clean();
wp_send_json_success( $data );
wp_die();
}
lazy-load.js
$('.unit-terms li a').each( function() {
if ( this.href == window.location.href ) {
$(this).parent().addClass('current');
}
});
main.js
(function($){
$('.isotope a').on('click', function(){
$('.isotope .active').removeClass('active');
$(this).addClass('active');
var filter = $(this).data('filter');
if(filter=='*'){
$('.property').show();
}else{
$('.property').not(filter).hide();
$('.property'+filter).show();
}
return false;
});
})(jQuery);
so how can i make it work? i don't know what im doing wrong here
Here is the repo link for the full project
https://github.com/Ov3rControl/hoomerz
ok, now I understand what you meant ;) During lazy load you send to backend only page number without current state of filters and / or search string. So it sends all posttype items based on page number only. You should send also current state of filters
main.js: add this to your after-page-load function:
var currentUrl = new URL(window.location.href);
var searchQuery = urlObj.searchParams.get("k");
lazy-load.js: add search param to data posted to backend
var data = {
'action': 'load_posts_by_ajax',
'page': page,
'search: searchQuery // new field
};
lazy-load.php: add search param to WP_Query
if ( isset($_POST['search']) && !empty($_POST['search']) ){ // new section
$args['s'] = sanitize_text_field($_POST['search']);
}
That's example for text search filter. For all filters you must
1. match every filter from front (URL get param) (main.js)
2. than put it in data object sent to backend (lazy-load.js)
3. address this variable in lazy-load.php in if(isset($_POST['param-name'])) section ( new or existing one as there are some )
I suggest to try without ob_start() / ob_get_clean(). Also if you generate html instead of raw data structure, I would simply print it to output without wp_send_json_success().
Other solution would be sending raw data (1. array in php, 2. json_encode(), 3. wp_send_json() ) and than processing in javascript (dynamic dom element creation after request to backend made).

ReferenceError: ajax_object is not defined when loading Wordpress post via Ajax

I've been trying to implement the recommendation by #SagiveSEO in this thread:
Proper way to load a single post via Ajax?
The idea: click a button and load a post via AJAX. The idea being that you'll have a tree of buttons to allow people to navigate quickly to useful content.
Unfortunately, it fails.
In the console I get the message "ReferenceError: ajax_object is not defined" which refers to the line "$.post(ajax_object.ajaxurl..."
What am I doing wrong?
Here's my HTML:
<button class="get_project" data-postid="3300">PROJECT NAME</button>
<div class="postcontainer"></div>
Here's my Javascript:
jQuery(function($){
$('.get_project').click(function() {
var postid = $(this).data('postid'); // Amended by #dingo_d
$.post(ajax_object.ajaxurl, {
action: 'my_load_ajax_content ',
postid: postid
}, function(data) {
var $response = $(data);
var postdata = $response.filter('#postdata').html();
$('.postcontainer').html(postdata);
});
})
//alert( "hello world" );
});
and here is the php from my functions.php file:
function my_load_ajax_content () {
$pid = intval($_POST['post_id']);
$the_query = new WP_Query(array('p' => $pid));
if ($the_query->have_posts()) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$data = '
<div class="post-container">
<div id="project-content">
<h1 class="entry-title">'.get_the_title().'</h1>
<div class="entry-content">'.get_the_content().'</div>
</div>
</div>
';
}
}
else {
echo '<div id="postdata">'.__('Didnt find anything', THEME_NAME).'</div>';
}
wp_reset_postdata();
echo '<div id="postdata">'.$data.'</div>';
}
// Next two lines corrected - thanks #dingo_d
add_action ( 'wp_ajax_my_load_ajax_content', 'my_load_ajax_content' );
add_action ( 'wp_ajax_nopriv_my_load_ajax_content', 'my_load_ajax_content' );
Also required in functions.php within the script enqueuing function:
wp_enqueue_script( 'myajaxpostloader', get_template_directory_uri().'/js/ajax.js', array( 'jquery' ), '1.0', true );
wp_localize_script( 'myajaxpostloader', 'ajax_object', array(
'ajaxurl' => admin_url( 'admin-ajax.php' )
));
(note that my Javascript is saved as /js/ajax.js where /js/ is a subdirectory of the Wordpress theme).
You didn't localize your ajax object. In Twenty fifteen theme you'd do it like this - in functions.php you'd put
wp_localize_script( 'twentyfifteen-script', 'ajax_object', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
));
Where your scripts are enqueued.
In your theme be sure to use proper handle - in stead of 'twentyfifteen-script' put the one where your ajax code is in. So if your ajax JavaScript is located in a file called custom.js, and you've enqueued that script with the handle custom_js, then you'd put
wp_localize_script( 'custom_js', 'ajax_object', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
));
After you've enqueued that script. All in all in your functions.php you'd put something like this:
add_action('after_setup_theme', 'mytheme_theme_setup');
if ( ! function_exists( 'mytheme_theme_setup' ) ){
function mytheme_theme_setup(){
add_action( 'wp_enqueue_scripts', 'mytheme_scripts');
}
}
if ( ! function_exists( 'mytheme_scripts' ) ){
function mytheme_scripts() {
wp_enqueue_script( 'custom_js', get_template_directory_uri().'/js/custom.js', array( 'jquery'), '1.0.0', true );
wp_localize_script( 'custom_js', 'ajax_object', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
));
}
}
Or at the very least look for such code and just place the localization there :)

Chained selects in Wordpress via AJAX

I need to make two chained select inputs (country, city) in WP.
(all is in locations taxonomy, country is a main category and city is a subcategory)
in first select i listed all countries:
$locations = get_terms( ‘locations’, array(
‘hide_empty’ => false,
‘parent’ => 0 ) );
In second select i need only the cities depend on selected country
(without page refresh/submit, so with AJAX)
I need passing selected value from first select to php variable:
$whichCountry = AJAX RESPONSE HERE
Listing second select:
$locations = get_terms( ‘locations’, array(
‘hide_empty’ => false,
‘parent’ => $whichCounty) );
Please help me how to achieve this
i make same code but its not enough:
JS:
(function ($) {
$(document).ready(function () {
$(‘#first_select’).on(‘change’, function(){
$.post(
PT_Ajax.ajaxurl,
{
// wp ajax action
action: ‘ajax-inputtitleSubmit’,
// vars
data: $(‘#first-select’).val(),
// send the nonce along with the request
nextNonce: PT_Ajax.nextNonce
},
function (response) {
console.log(response.data);
}
);
return false;
});
});
})(jQuery);
PHP:
add_action( ‘wp_enqueue_scripts’, ‘inputtitle_submit_scripts’ );
add_action( ‘wp_ajax_ajax-inputtitleSubmit’, ‘myajax_inputtitleSubmit_func’ );
add_action( ‘wp_ajax_nopriv_ajax-inputtitleSubmit’, ‘myajax_inputtitleSubmit_func’ );
function inputtitle_submit_scripts() {
wp_enqueue_script( ‘inputtitle_submit’, get_template_directory_uri() . ‘/assets/js/inputtitle_submit.js’, array( ‘jquery’ ) );
wp_localize_script( ‘inputtitle_submit’, ‘PT_Ajax’, array(
‘ajaxurl’ => admin_url( ‘admin-ajax.php’ ),
‘nextNonce’ => wp_create_nonce( ‘myajax-next-nonce’ )
)
);
}
function myajax_inputtitleSubmit_func() {
// check nonce
$nonce = $_POST[‘nextNonce’];
if ( ! wp_verify_nonce( $nonce, ‘myajax-next-nonce’ ) ) {
die ( ‘Busted!’ );
}
// generate the response
$response = json_encode( $_POST );
// response output
header( “Content-Type: application/json” );
$whichCountry = $response;
// IMPORTANT: don’t forget to “exit”
exit;
}
Functions.php
include_once(‘inputtitle_submit_inc.php’)

Resources