1

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.

1 Answer 1

1

I figured it out. Instead of trying to combine the two functions together in my functions.php file, I added both of them. Why did this work? Because one is adding a new comment (via a call to ajax-comments.php) and the other function is querying all the existing comments. So it's something like this:

  1. My original html5blankcomments() function grabbed the existing WP comments.
  2. the misha_submit_ajax_comment() function (that you can see in the tutorial link I posted in my question) talks to the ajax-comments.php file and just works on submitting (and displaying) the new comment.
  3. With both functions running, we get the old comments (html5blankcomments()) and the new comments misha_submit_ajax_comment() showing up without page refresh.

Because they both need to exist, combining them was not the answer. I thought it could all happen in one function (and perhaps it can), but that was not how the tutorial code was written.

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.