I'm trying to implement Ajax for my comments in WordPress, using this tutorial. But I'm running into issues when integrating the code from the tutorial into my own pre-built theme. The issue is that I either get a WP error of 'Duplicate comment detected; it looks as though you've already said that!'or a standard 500 error. Here's what I've got:
Here's what my ajax-comments.js file looks like:
* Let's begin with validation functions
*/
jQuery.extend(jQuery.fn, {
/*
* check if field value lenth more than 3 symbols ( for name and comment )
*/
validate: function () {
if (jQuery(this).val().length < 3) {jQuery(this).addClass('error');return false} else {jQuery(this).removeClass('error');return true}
},
/*
* check if email is correct
* add to your CSS the styles of .error field, for example border-color:red;
*/
validateEmail: function () {
var emailReg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/,
emailToValidate = jQuery(this).val();
if (!emailReg.test( emailToValidate ) || emailToValidate == "") {
jQuery(this).addClass('error');return false
} else {
jQuery(this).removeClass('error');return true
}
},
});
jQuery(function($){
/*
* On comment form submit
*/
$( '#commentform' ).submit(function(){
// define some vars
var button = $('#submit'), // submit button
respond = $('#respond'), // comment form container
commentlist = $('.comment-list'), // comment list container
cancelreplylink = $('#cancel-comment-reply-link');
// if user is logged in, do not validate author and email fields
/*
if( $( '#author' ).length )
$( '#author' ).validate();
if( $( '#email' ).length )
$( '#email' ).validateEmail();
*/
// validate comment in any case
$( '#comment' ).validate();
// if comment form isn't in process, submit it
if ( !button.hasClass( 'loadingform' ) && !$( '#author' ).hasClass( 'error' ) && !$( '#comment' ).hasClass( 'error' ) ){
// ajax request
$.ajax({
type : 'POST',
url : html5_comment_params.ajaxurl, // admin-ajax.php URL
data: $(this).serialize() + '&action=ajaxcomments', // send form data + action parameter
beforeSend: function(xhr){
// what to do just after the form has been submitted
button.addClass('loadingform').val('Loading...');
},
error: function (request, status, error) {
if( status == 500 ){
alert( 'Error while adding comment' );
} else if( status == 'timeout' ){
alert('Error: Server doesn\'t respond.');
} else {
// process WordPress errors
var wpErrorHtml = request.responseText.split("<p>"),
wpErrorStr = wpErrorHtml[1].split("</p>");
alert( wpErrorStr[0] );
}
},
success: function ( addedCommentHTML ) {
// if this post already has comments
if( commentlist.length > 0 ){
// if in reply to another comment
if( respond.parent().hasClass( 'comment' ) ){
// if the other replies exist
if( respond.parent().children( '.children' ).length ){
respond.parent().children( '.children' ).append( addedCommentHTML );
} else {
// if no replies, add <ol class="children">
addedCommentHTML = '<ol class="children">' + addedCommentHTML + '</ol>';
respond.parent().append( addedCommentHTML );
}
// close respond form
cancelreplylink.trigger("click");
} else {
// simple comment
commentlist.append( addedCommentHTML );
}
}else{
// if no comments yet
addedCommentHTML = '<ol class="comment-list">' + addedCommentHTML + '</ol>';
respond.before( $(addedCommentHTML) );
}
// clear textarea field
$('#comment').val('');
},
complete: function(){
// what to do after a comment has been added
button.removeClass( 'loadingform' ).val( 'Post Comment' );
}
});
}
return false;
});
});
I've registered and enqueued it in my functions.php file, like so:
function misha_ajax_comments_scripts() {
// I think jQuery is already included in your theme, check it yourself
wp_enqueue_script('jquery');
// just register for now, we will enqueue it below
wp_register_script( 'ajax_comment', get_stylesheet_directory_uri() . '/ajax-comment.js', array('jquery') );
// let's pass ajaxurl here, you can do it directly in JavaScript but sometimes it can cause problems, so better is PHP
wp_localize_script( 'ajax_comment', 'html5_comment_params', array(
'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php'
) );
wp_enqueue_script( 'ajax_comment' );
}
and have also leveraged the custom function that my theme uses for comments (also in functions.php):
add_action( 'wp_ajax_ajaxcomments', 'html5blankcomments' ); // wp_ajax_{action} for registered user
add_action( 'wp_ajax_nopriv_ajaxcomments', 'html5blankcomments' ); // wp_ajax_nopriv_{action} for not registered users
// Custom Comments Callback
function html5blankcomments($comment, $args, $depth)
{
$comment = wp_handle_comment_submission( wp_unslash( $_POST ) );
extract($args, EXTR_SKIP);
if ( is_wp_error( $comment ) ) {
$error_data = intval( $comment->get_error_data() );
if ( ! empty( $error_data ) ) {
wp_die( '<p>' . $comment->get_error_message() . '</p>', __( 'Comment Submission Failure' ), array( 'response' => $error_data, 'back_link' => true ) );
} else {
wp_die( 'Unknown error' );
}
}
if ( 'div' == $args['style'] ) {
$tag = 'div';
$add_below = 'comment';
} else {
$tag = 'li';
$add_below = 'div-comment';
}
/*
* Set Cookies
*/
$user = wp_get_current_user();
do_action('set_comment_cookies', $comment, $user);
$GLOBALS['comment'] = $comment;
?>
<!-- heads up: starting < for the html tag (li or div) in the next line: -->
<<?php echo $tag ?> <?php comment_class(empty( $args['has_children'] ) ? '' : 'parent') ?> id="comment-<?php comment_ID() ?>">
<?php if ( 'div' != $args['style'] ) : ?>
<div id="div-comment-<?php comment_ID() ?>" class="comment-body">
<?php endif; ?>
<div class="comment-author vcard">
<?php printf(__('<cite class="fn">%s</cite><span class="says"> </span'), get_comment_author_link()) ?><a href="<?php echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ) ?>"></a>
<?php
printf( _x( '%s ago', '%s = human-readable time difference', 'your-text-domain' ), human_time_diff( get_comment_time( 'U' ), current_time( 'timestamp' ) ) );
?>
</div>
<?php comment_text() ?>
<?php if( get_field('commenter_rating_number', $comment) ): ?>
<span class="commenter-rating"><ion-icon name="star"></ion-icon><?php the_field('commenter_rating_number', $comment); ?></span>
<?php endif; ?>
<div class="comment-meta commentmetadata"><?php edit_comment_link(__('(Edit)'),' ','' );
?>
</div>
<div class="reply">
<?php comment_reply_link(array_merge( $args, array('add_below' => $add_below, 'depth' => $depth, 'max_depth' => $args['max_depth']))) ?>
</div>
<?php if ( 'div' != $args['style'] ) : ?>
</div>
<?php endif; ?>
<div class="separator"></div>
<?php }
Finally, this is the code that outputs it in the theme itself - the comments.php file:
<?php comment_form(array(
'title_reply' => '',
// Redefine your own textarea (the comment body).
'comment_field' => '<p class="comment-form-comment"><label for="comment">' . _x( 'Comments', 'noun' ) . '</label><textarea id="comment" name="comment" aria-required="true" placeholder="What are your thoughts?"></textarea></p>',
)); ?>
<?php if (have_comments()) : ?>
<h5><?php comments_number(); ?></h5>
<ul class="comment-list">
<?php wp_list_comments('type=comment&callback=html5blankcomments'); // Custom callback in functions.php ?>
</ul>
<?php elseif ( ! comments_open() && ! is_page() && post_type_supports( get_post_type(), 'comments' ) ) : ?>
<p><?php _e( 'Comments are closed here.', 'html5blank' ); ?></p>
<?php endif; ?>
Any thoughts? I'm looking at the variables that are being passed and everything seems correct, but with those errors I feel like I might be overlooking something just as simple as that.
Any help is immensely appreciated.