WordPress 3.0 has something very handy that I want theme authors to start implementing as soon as possible.
To show exactly why it’s so useful, I modified my own theme to start using it.
Demonstration
So, here’s a big hunk of code I pulled out of my current theme’s comments.php. This hunk of code has only one purpose: To display the form area where people can leave a comment:
<?php if ('open' == $post->comment_status) : ?> <div id="respond"> <h3><?php comment_form_title( 'Leave a Reply', 'Leave a Reply to %s' ); ?></h3> <div class="cancel-comment-reply"> <small><?php cancel_comment_reply_link(); ?></small> </div> <?php if ( get_option('comment_registration') && !$user_ID ) : ?> <p>You must be <a href="<?php echo get_option('siteurl'); ?>/wp-login.php?redirect_to=<?php echo urlencode(get_permalink()); ?>">logged in</a> to post a comment.</p> <?php else : ?> <form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform"> <?php if ( $user_ID ) : ?> <p>Logged in as <a href="<?php echo get_option('siteurl'); ?>/wp-admin/profile.php"><?php echo $user_identity; ?></a>. <a href="<?php echo wp_logout_url(get_permalink()); ?>" title="Log out of this account">Log out »</a></p> <?php else : ?> <p><input type="text" name="author" id="author" value="<?php echo $comment_author; ?>" size="22" tabindex="1" /> <label for="author"><small>Name <?php if ($req) echo "(required)"; ?></small></label></p> <p><input type="text" name="email" id="email" value="<?php echo $comment_author_email; ?>" size="22" tabindex="2" /> <label for="email"><small>Mail (will not be published) <?php if ($req) echo "(required)"; ?></small></label></p> <p><input type="text" name="url" id="url" value="<?php echo $comment_author_url; ?>" size="22" tabindex="3" /> <label for="url"><small>Website</small></label></p> <?php endif; ?> <!--<p><small><strong>XHTML:</strong> You can use these tags: <code><?php echo allowed_tags(); ?></code></small></p>--> <p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p> <p><input name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" /> <?php comment_id_fields(); ?> </p> <?php do_action('comment_form', $post->ID); ?> </form> <?php endif; // If registration required and not logged in ?> </div> <?php endif; // if you delete this the sky will fall on your head ?>
Nasty, eh? It’s a mess of if/else statements. It handles cases where the user is logged in or not, where the comments are open or closed, whether registration is required, etc. It’s confusing, difficult to modify, poor for CSS referencing…
Here’s what I replaced all that code with:
<?php comment_form(); ?>
Now then, that’s much better, isn’t it?
The comment_form function is new to 3.0. Basically, it standardizes the comments form. It makes it wonderful for us plugin authors, since now we can easily modify the comments form with various hooks and things. I’ve already modified Simple Facebook Connect and Simple Twitter Connect to support this new approach; if you’re using a theme with this, then the user won’t have to modify it to have their buttons appear on the comments form.
Customizing
Since theme authors love to customize things, the comments form is also extremely customizable. Doing it, however, can be slightly confusing.
Inside the comments_form function, we find some useful hooks to let us change things around.
The first hook is comment_form_default_fields. This lets us modify the three main fields: author, email, and website. It’s a filter, so we can change things as they pass through it. The fields are stored in an array which contains the html that is output. So it looks sorta like this:
array( 'author' => '<p class="comment-form-author">...', 'email' => '<p class="comment-form-email">...', 'url' => '<p class="comment-form-url">...' );
I truncated it for simplicity. But what this means is that code like this can modify the fields:
function my_fields($fields) { $fields['new'] = '<p>Some new input field here</p>'; return $fields; } add_filter('comment_form_default_fields','my_fields');
That sort of thing lets us add a new input field, or modify the existing ones, etc…
But fields aren’t the only thing we can change. There’s a comment_form_defaults filter too. It gets a lot of the surrounding text of the comments form. The defaults look sorta like this:
$defaults = array( 'fields' => apply_filters( 'comment_form_default_fields', $fields ), 'comment_field' => '<p class="comment-form-comment">...', 'must_log_in' => '<p class="must-log-in">...', 'logged_in_as' => '<p class="logged-in-as">...', 'comment_notes_before' => '<p class="comment-notes">...', 'comment_notes_after' => '<dl class="form-allowed-tags">...', 'id_form' => 'commentform', 'id_submit' => 'submit', 'title_reply' => __( 'Leave a Reply' ), 'title_reply_to' => __( 'Leave a Reply to %s' ), 'cancel_reply_link' => __( 'Cancel reply' ), 'label_submit' => __( 'Post Comment' ), );
All the various pieces of html that are displayed as part of the comment form section are defined here. So those can be modified as you see fit. However, unlike the fields, adding new bits here won’t help us at all. The fields get looped through for displaying them, these are just settings that get used at various times.
But filters are not the only way to modify these. The comment_form function actually can take an array of arguments as the first parameter, and those arguments will modify the form. So if we wanted a simple change, like to change the wording of “Leave a Reply”, then we could do this:
<?php comment_form(array('title_reply'=>'Leave a Reply, Stupid')); ?>
This gives us a simple and easy way to make changes without all the trouble of filters. Nevertheless, those filters can be very useful for more complex operations.
But wait, there’s more!
As the comments form is being created, there’s a ton of action hooks being called, at every stage. So if you want to insert something into the form itself, there’s easy ways to do it.
A quick list of the action hooks. Most of them are self-explanatory.
- comment_form_before
- comment_form_must_log_in_after
- comment_form_top
- comment_form_logged_in_after
- comment_notes_before
- comment_form_before_fields
- comment_form_field_{$name} (a filter on each and every field, where {$name} is the key name of the field in the array)
- comment_form_after_fields
- comment_form_field_comment (a filter on the “comment_field” default setting, which contains the textarea for the comment)
- comment_form (action hook after the textarea, for backward compatibility mainly)
- comment_form_after
- comment_form_comments_closed
CSS and other extras
Let’s not forget styling. All parts of the comments form have nice classes and id’s and such. Take a look at the resulting HTML source and you’ll find all the styling capabilities you like. Also, everything is properly semantic, using label tags and aria-required and so forth. All the text is run through the translation system for core translations.
So theme authors should start modifying their themes to use this instead of the existing big-ugly-comment-form code. Your users will thank you for it. Plugin authors will thank you for it. And really, it’s about time we made WordPress themes more about design and less about the nuts and bolts of the programming, no?
Comment Form Autocomplete Snippet
Google came out with an experimental specification for websites to provide “hints” on forms, to allow things like autocomplete to work better and be more standardized. Seems useful.
Here’s a quick plugin snippet you can use to make your comments form use this specification. Only Chrome 15 and up is using this at the moment, but in the long run I think most browsers will be implementing something similar to this, since filling out forms is just one of those endless pieces of drudgery that we could all stand to do away with.
Note that your theme will need to be using the comment_form() function call for this to work, otherwise you’ll just have to edit your comment form in the theme manually.
Simple little bit of code, really. Should work with any theme using the normal comment_form() function call.
Category: Code, WordPress | 2 Comments