Customizing WordPress comments

The documentation on customizing WordPress comments is a bit sparse, particularly when compared to WordPress posts. I ran into this issue while building a web application built off of WordPress and wanted to use WordPress’ commenting system with some custom fields and styling. So here’s my attempt to address that.

  1. Make sure you have a comments.php template file for your theme – create one if needed. I recommend looking at _s for a good model.
  2. See the following code below – it should be pretty obvious with its inline commenting. Please excuse any WordPress code formatting issues.
  3. With this code we can now wrap your comment markup with our own tags and classes as well as display our own custom comment fields/data using get_comment_meta().
  4. The WordPress core comment-template.php file had the clues I needed to figure this out. I saw how they were structuring and coding things so I translated that code into my comments.php theme file, tested, and tidied it up until it worked. Now to the code…
<?php
/*
 If the current post is protected by a password and
 the visitor has not yet entered the password we will
 return early without loading the comments.
 */
if ( post_password_required() ) {
    return;
}
?>
<?php // Now our comments area ?>
<div id="comments" class="comments-area">
    <?php //check to see if we have comments
    if ( have_comments() ) : ?>
        <h2 class="comments-title">
            <?php
                printf( // WPCS: XSS OK.
                    esc_html( _nx( 'One comment on &ldquo;%2$s&rdquo;', '%1$s comments on &ldquo;%2$s&rdquo;', get_comments_number(), 'comments title', '_s' ) ),
                    number_format_i18n( get_comments_number() ),
                    '<span>' . get_the_title() . '</span>'
                );
            ?>
        </h2>
    <?php if ( get_comment_pages_count() > 1 && get_option( 'page_comments' ) ) : // Are there comments to navigate through? ?>
        <nav id="comment-nav-above" class="navigation comment-navigation" role="navigation">
            <h2 class="screen-reader-text"><?php esc_html_e( 'Comment navigation', '_s' ); ?></h2>
            <div class="nav-links">
<?php //comment navigation links ?>

                <div class="nav-previous"><?php previous_comments_link( esc_html__( 'Older Comments', '_s' ) ); ?></div>
                <div class="nav-next"><?php next_comments_link( esc_html__( 'Newer Comments', '_s' ) ); ?></div>

            </div><!-- .nav-links -->
        </nav><!-- #comment-nav-above -->
        <?php endif; // Check for comment navigation. ?>

    <ol class="comment-list">
            <?php if ( have_comments() ) : //possibly duplicative, but this works ?>
            <?php while (have_comments() ) : the_comment(); //the loop, but for comments ?>
            <li id="comment-<?php comment_ID(); ?>" <?php comment_class(); ?>>
            <article id="div-comment-<?php comment_ID(); ?>" class="comment-body">
                <footer class="comment-meta">
                    <div class="comment-author vcard">
                        <?php echo get_avatar( $comment->comment_ID ); ?>
                        <?php printf( __( '%s <span class="says">says:</span>' ), sprintf( '<strong class="fn">%s</strong>', get_comment_author_link() ) ); ?>
                    </div><!-- .comment-author -->

                    <div class="comment-metadata">
                        <a href="<?php echo esc_url( get_comment_link( $comment->comment_ID ) ); ?>">
                            <time datetime="<?php comment_time( 'c' ); ?>">
                                <?php printf( _x( '%1$s at %2$s', '1: date, 2: time' ), get_comment_date(), get_comment_time() ); ?>
                            </time>
                        </a>
                        <?php edit_comment_link( __( 'Edit' ), '<span class="edit-link">', '</span>' ); ?>
                    </div><!-- .comment-metadata -->

                    <?php if ( '0' == $comment->comment_approved ) : //is the comment in moderation ?>
                        <p class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.' ); ?></p>
                    <?php endif; ?>
                </footer><!-- .comment-meta -->

                <div class="comment-content">
                <?php
                comment_text(); //the actual comment content 
                ?>
                </div><!-- .comment-content -->

                <?php
                comment_reply_link(); // the reply to a comment link
                ?>
            </article><!-- .comment-body -->
            </li>
                        <?php endwhile; ?>
            <?php endif; //closing out our comment loop 
            ?>
        </ol><!-- .comment-list -->
    <?php
        // If comments are closed and there are comments, let's leave a little note, shall we?
        if ( ! comments_open() && get_comments_number() && post_type_supports( get_post_type(), 'comments' ) ) :
    ?>
        <p class="no-comments"><?php esc_html_e( 'Comments are closed.', '_s' ); ?></p>
    <?php endif; ?>

    <?php comment_form(); //the comment form ?>

</div><!-- #comments -->

CSS classes based on page location

When styling SharePoint sites, it can be very useful to add specific styles to specific “pages” or views. Here’s a bit of jQuery/javascript code to make that possible. It works by grabbing the page location turning it into classes that are added to the body tag.


jQuery(document).ready(function($){
//use a javascript variable to hold the results of jQuery's "find the body tag" call
var $body = $('body');
//use a variable to capture and store the page url, also removing the 'http(s)://'
var url = window.location.href.replace(/http[s]?:\/\//, '');
//replace any .html, .asp(x), .php or .jsp file extensions
url = url.replace(/\.(htm[l]?|asp[x]?|php|jsp)$/,'');
//replace any '.' with '_' - ie. 'example.com' will become 'example_com'
url = url.replace(/[.]/g, "_");
//Wherever there is a '/', split url into a segment
var segments = url.split('/');
//Take these segments and add them as classes to the body
for (var i = 0; i < segments.length; i++) { $body.addClass(segments[i]); } });

For servers that prefer case sensitivity but allow either case to work (like SharePoint), and where that may cause unwanted headaches you can replace the line where we first define 'var url' with this:

var url = window.location.href.toLowerCase().replace(/http[s]?:\/\//, '');

Nearly automatic breadcrumbs

Breadcrumbs

var here = location.href.replace(/(\?.*)$/,'').split('/').slice(3);

var parts = [{ "text": 'Home', "link": '/' }];

for( var i = 0; i < here.length; i++ ) {
var part = here[i];
var pageName = part.toLowerCase();
pageName = part.charAt(0).toUpperCase() + part.slice(1);
var link = '/' + here.slice( 0, i + 1 ).join('/');
$('#siteBreadcrumb ol.breadcrumb').append('<li><a href="' + link +'">' + pageName.replace(/\.(htm[l]?|asp[x]?|php|jsp)$/,'') + '</a></li>');
parts.push({ "text": pageName, "link": link });
}

Generates breadcrumb links based on the URL/path of the document.