0

I wrote a code for a plugin which suppose to modify the WordPress dashboard to display a cog icon for each post in a column named "Optimize". I added an action to the icon that triggers the opening of a window on URL https://khoreketab.com/seo-optimization. Here is my plugin code:

<?php
/*
Plugin Name: My Plugin
Description: Add a cog icon to the WordPress dashboard for each post and open a new window on 
URL https://khoreketab.com/seo-optimization when the icon is clicked.
Version: 1.0
Author: Shima
*/

// Add column to the post list table
add_filter( 'manage_post_posts_columns', 'myplugin_add_optimize_column' );
function myplugin_add_optimize_column( $columns ) {
    $columns['optimize'] = __( 'Optimize', 'my-plugin' );
    return $columns;
}

// Display the cog icon in each row of the "Optimize" column
add_action( 'manage_post_posts_custom_column', 'myplugin_display_optimize_column', 10, 2 );
function myplugin_display_optimize_column( $column, $post_id ) {
    if ( 'optimize' === $column ) {
        echo '<span class="dashicons dashicons-admin-generic" id="optimize-icon" data-post-id="' . esc_attr( $post_id ) . '" data-post-title="' . esc_attr( get_post_field( 'post_title', $post_id ) ) . '"></span>';
    }
}

// Enqueue the JavaScript file
add_action( 'admin_enqueue_scripts', 'myplugin_enqueue_scripts' );
function myplugin_enqueue_scripts() {
    wp_enqueue_script( 'jquery' );
    wp_enqueue_script( 'my-plugin', plugin_dir_url( __FILE__ ) . 'my-plugin.js', array( 'jquery' ), '1.0', true );
    wp_localize_script( 'my-plugin', 'myplugin_ajax_object', array(
        'ajax_url' => admin_url( 'admin-ajax.php' ),
        'nonce' => wp_create_nonce( 'myplugin-nonce' ),
        'post_title_label' => __( 'Post Title', 'my-plugin' ),
        'optimization_keyword_label' => __( 'Optimization Keyword', 'my-plugin' ),
        'submit_label' => __( 'Submit', 'my-plugin' )
    ) );
}

// Handle form submission via AJAX
add_action( 'wp_ajax_myplugin_optimize_post', 'myplugin_optimize_post' );
function myplugin_optimize_post() {
    // Check the nonce for security
    check_ajax_referer( 'myplugin-nonce', 'nonce' );

    // Get the post ID and optimization keyword from the request data
    $post_id = intval( $_POST['post_id'] );
    $optimization_keyword = sanitize_text_field( $_POST['optimization_keyword'] );

    // Do something here, like optimize the post's SEO or run some other action

    // Send a success response back to the client
    wp_send_json_success();
}

// Get the post title via AJAX
add_action( 'wp_ajax_myplugin_get_post_title', 'myplugin_get_post_title' );
add_action( 'wp_ajax_nopriv_myplugin_get_post_title', 'myplugin_get_post_title' );
function myplugin_get_post_title() {
// Check the nonce for security
check_ajax_referer( 'myplugin-nonce', 'nonce' );

$post_id = intval( $_POST['post_id'] );
$post_title = get_the_title( $post_id );
wp_send_json( $post_title );
}
?>

I also created a new file named my-plugin.js and save it in the same directory I saved the PHP file and with the same name (../my-plugin/my-plugin.js). Here is the code:

var $j = jQuery.noConflict(); // Use $j instead of $ to reference jQuery

$j(document).ready(function($) {
// When the cog icon is clicked
$(document).on('click', '#optimize-icon', function() {
    // Get the post ID and post title
    var post_id = $(this).data('post-id');
    var post_title = $(this).data('post-title');

    // Open a new window with the form
    var new_window = window.open('https://khoreketab.com/seo-optimization', 'new_window', 'noopener,width=400,height=400');
    new_window.onload = function() {
        // Get the post title via AJAX
        $j.ajax({
            type: 'POST',
            url: myplugin_ajax_object.ajax_url,
            data: {
                action: 'myplugin_get_post_title',
                post_id: parseInt(post_id),
                nonce: myplugin_ajax_object.nonce
            },
            beforeSend: function(xhr) {
                xhr.setRequestHeader('X-WP-Nonce', myplugin_ajax_object.nonce);
            },
            success: function(response) {
                // Populate the post title field
                new_window.document.getElementById('post_title').value = response;
            },
            error: function(error) {
                console.log(error);
            }
        });

        // Handle form submission
        $(new_window.document).on('submit', 'form', function(event) {
            event.preventDefault();

            // Get the optimization keyword
            var optimization_keyword = new_window.document.getElementById('optimization_keyword').value;

            // Run the optimization action via AJAX
            $j.ajax({
                type: 'POST',
                url: myplugin_ajax_object.ajax_url,
                data: {
                    action: 'myplugin_optimize_post',
                    post_id: parseInt(post_id),
                    optimization_keyword: optimization_keyword,
                    nonce: myplugin_ajax_object.nonce
                },
                beforeSend: function(xhr) {
                    xhr.setRequestHeader('X-WP-Nonce', myplugin_ajax_object.nonce);
                },
                success: function(response) {
                    console.log(response);
                },
                error: function(error) {
                    console.log(error);
                }
            });

            // Close the window
            new_window.close();
        });
    };
});

});

The JS code suppose to show a form, when the window pops up, which has 2 fields and a submit button. The first field (called "Post Title") should be automatically filled with the the post's title of that row from database, and the second field (named "Optimization Keyword") asks for an input keyword. I also create a new page on URL 'https://khoreketab.com/seo-optimization' with this HTML code:

Post Title:
<div style="margin-top: 10px;">
    <label for="optimization_keyword">Optimization Keyword:</label>
    <input type="text" id="optimization_keyword" name="optimization_keyword" value="">
</div>

<div style="margin-top: 20px;">
    <input type="submit" value="Submit">
</div>

Now, the problem is pressing the cog button, when the window pops up the post title's field is empty (It doesn't retrieve data from database) and The console shows these errors: to load resource: net::ERR_BLOCKED_BY_CLIENT dev-tools.min.js:2 Scroll util from "/dev/js/frontend/utils/scroll" is hard deprecated since 3.1.0 - Use elementorModules.utils.Scroll instead consoleWarn @ dev-tools.min.js:2 dev-tools.min.js:2 elementorCommon.helpers.softDeprecated is hard deprecated since 3.7.0 - Use elementorDevTools.deprecation.deprecated instead c

I tried these solutions:

  1. I disabled ad-blockers and all my browser extensions (I am using Brave).
  2. I checked for conflicts with other plugins and disabled the two conflicting plugins to see if that resolves the issue.

The number of errors reduced but there are still errors you see above. Can anyone help me with troubleshooting this issue so that the post title field be filled by database? Thank you so much.

1 Answer 1

1

The issue is that your JavaScript code is trying to retrieve and populate the post title in the new window, which is on a different domain (khoreketab.com), while the AJAX request to get the post title is being made to your WordPress site. This leads to a cross-origin resource sharing (CORS) issue. Due to security reasons, browsers prevent AJAX requests from one domain to access resources from another domain.

To resolve this issue, you can populate the post title from your main site and pass it to the new window using URL parameters. Here's how to do this:

  1. Add the data-post-title attribute to the cog icon in your main site. You should be able to find the code that generates the cog icon within your WordPress theme or plugin:
<i id="optimize-icon" data-post-id="<?php echo $post_id; ?>" data-post-title="<?php echo esc_attr(get_the_title($post_id)); ?>" class="fa fa-cog"></i>

Make sure you replace the <?php echo $post_id; ?> and <?php echo esc_attr(get_the_title($post_id)); ?> with the actual PHP code that retrieves the post ID and title in your implementation.

  1. Modify your JavaScript code in my-plugin.js to pass the post title as a URL parameter:
// When the cog icon is clicked
$(document).on('click', '#optimize-icon', function() {
    // Get the post ID and post title
    var post_id = $(this).data('post-id');
    var post_title = encodeURIComponent($(this).data('post-title'));

    // Open a new window with the form and post title as a URL parameter
    var new_window = window.open('https://khoreketab.com/seo-optimization?post_title=' + post_title, 'authWindow', 'noopener,width=400,height=400');
    
    // Rest of the code...
});
  1. Modify the HTML code on your 'https://khoreketab.com/seo-optimization' page to include an ID for the form and change the input type of the submit button to "button":
<form id="optimize-form">
    Post Title:
    <input type="text" id="post_title" name="post_title" value="">
    <div style="margin-top: 10px;">
        <label for="optimization_keyword">Optimization Keyword:</label>
        <input type="text" id="optimization_keyword" name="optimization_keyword" value="">
    </div>

    <div style="margin-top: 20px;">
        <input type="button" value="Submit">
    </div>
</form>
  1. Modify your JavaScript code in my-plugin.js to populate the post title from the URL parameter when the new window loads:
new_window.onload = function() {
    // Get the post title from the URL parameter
    var urlParams = new URLSearchParams(new_window.location.search);
    var post_title = urlParams.get('post_title');
    
    // Populate the post title field
    new_window.document.getElementById('post_title').value = decodeURIComponent(post_title);

    // Rest of the code...
};

With these changes, the post title should be passed to the new window and populate the "Post Title" field. The CORS issue should no longer occur, as you are no longer making an AJAX request to fetch the post title.

8
  • Thank you Rustvik Panchal for your explanations. I changed the codes as you suggested. Now, in the popped up window I see an empty Post Title field which allows for typing an input. But still it is not filled. May 3, 2023 at 9:30
  • Apologies for the confusion. It seems I missed the part where the data-post-title attribute needs to be added to the cog icon in your main site. I'll update the answer with proper needful thing. May 3, 2023 at 9:38
  • @ShimaMasaeli I've updated the answer with proper changes please check May 3, 2023 at 9:42
  • Let me check the code with you @Rutvik Panchal, to see if I implement it correctly. I replace this statement echo <span class="dashicons dashicons-admin-generic" id="optimize-icon" data-post-id="' . esc_attr( $post_id ) . '" data-post-title="' . esc_attr( get_post_field( 'post_title', $post_id ) ) . '"></span>; with echo '<i id="optimize-icon" data-post-id="' . esc_attr( $post_id ) . '" data-post-title="' . esc_attr( get_the_title( $post_id ) ) . '" class="fa fa-cog"></i>'; May 3, 2023 at 10:30
  • with such replacement the Post Title field is still empty. May 3, 2023 at 10:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.