Seems to me that the only problem is that you put the full approve url in the link, in this ways when you click the link you trigger the ajax and open the page url in the link.
To be more clear your link is something like:
<a class="p3-comment-moderation" href="https://wordpress.stackexchange.com/questions/128383/admin-ajax.php?action=p3_comment_approve&comment_id=123&nonce=xxxxx" data-comment_id="123" data-nonce="xxxxx">Approve</a>
thanks to the javascript, when you click on the link you launch an ajax request but, there is nothing that prevent the default link behaviour to be triggered, and so the admin-ajax.php
is required to the browser, and thanks to the header
statement in your code, then the page comes back again to current page.
So, actually, this is what happen:
- the ajax is triggered
admin-ajax.php
is open by the url in thea
tag- the page is sended again to previous page because of the
header("Location: ".$_SERVER["HTTP_REFERER"])
statement in your code
I know that putting the full url in the link is the right way to make it works even if the user has javascript disabled, but when javascript is enabled you must prevent the default link behaviour, this can be done via the preventDefault()
js function.
So, in your javascript replace
jQuery(".p3-comment-moderation").click( function() {
with
jQuery(".p3-comment-moderation").click( function(e) {
e.preventDefault();
After that everything should work as expected.
If, like I guess, this is the only problem, this question is a pure javascript one, so off-topic here. However, to make my answer more WordPress relevant I want add some tips (nothing that make the script work or not, just best practice and improvements).
Tip 1: Escape attributes and links
When in WordPress you output something in the html output as tag property, best practice is escape it with esc_attr
, in general use all esc_*
function when applyable
$p3_edit_links="<a class="p3-comment-moderation" href="" . $p3_approve_link . '" data-comment_id="' . $comment_id . '" data-nonce="' . $nonce . '">Approve</a>';
is better wrote:
$p3_edit_links_f="<a class="p3-comment-moderation" href="https://wordpress.stackexchange.com/questions/128383/%s" data-comment_id="%d" data-nonce="https://wordpress.stackexchange.com/questions/128383/%s">";
$p3_edit_links = sprintf($p3_edit_links_f, esc_url($p3_approve_link), esc_attr($comment_id), esc_attr($nonce) );
I know that you getting urls and attributes from WP core functions, however once almost all output from core can be filtered is good to apply data validation (although data validation functions can filtered too…)
Tip 2: use core constant to check ajax requests
In your code there’s
if( ! empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
to check if the current request is from ajax. In WordPress when you properly use admin-ajax.php
(like you do) you can check ajax request looking for DOING_AJAX
constant, so the previous conditional statement becomes:
if ( defined('DOING_AJAX') && DOING_AJAX ) {
Tip 3: use core function to output json and exit script
Your code
$result = json_encode($result);
echo $result;
...
die();
can be wrote in one line, using the core wp_send_json
function
wp_send_json( $result );
Tip 4: avoid direct superglobals access
when you have to handle superglobals ($_REQUEST
, $_GET
, $_POST
…) to avoid notices you should always check that the key you are looking for is setted, so your
if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'p3_comment_moderation' ) ) {
is better wrote:
if ( ! isset($_REQUEST['nonce']) || ! wp_verify_nonce( $_REQUEST['nonce'], 'p3_comment_moderation' ) ) {
However, is even better to use filter_var
instead of accessing superglobals directly
$nonce = filter_var( INPUT_GET, 'nonce', FILTER_VALIDATE_STRING);
if ( empty($nonce) ) $nonce = filter_var( INPUT_POST, 'nonce', FILTER_VALIDATE_STRING);
if ( ! wp_verify_nonce( $nonce, 'p3_comment_moderation' ) ) {