ドキュメント

Tutorials:Really Simple Live Comment Preview

From jQuery JavaScript Library

Jump to: navigation, search

Adding a live preview to the comment entry area of Wordpress.

Original: http://www.learningjquery.com/2006/11/really-simple-live-comment-preview
Author: Karl Swedberg

Similar Tutorials: EventsAttributesForms

Contents

Introduction and Caveat

Please keep in mind as you read through this tutorial the "learning" part of this site's title: I'm learning jQuery just as many of those who will read this entry are. I mention this now because I have the nagging feeling that it was just too easy to create the live preview. Surely I must be doing something wrong. As always, I am counting on the superior knowledge of my readers to point out where my code fails. But enough of the apologies. Let's get started.

Quick Setup

For the live preview I started with the default comment form in WordPress's Kubrick template:

 <form action="..." method="post" id="commentform">
   <p><textarea name="comment" id="comment" cols="100" rows="10" tabindex="4"></textarea></p>
   <p>
     <input name="submit" id="submit" tabindex="5" value="Submit Comment" type="submit">
     <input name="comment_post_ID" value="30" type="hidden">
   </p>
 </form>

The important part here is the textarea's id="comment". We want to show the contents of that textarea as the user inputs them.

Create the Preview DIV

Now on to the jQuery code. We first need to create a container in which we can inject the comment text. The container could have been a part of the HTML, or it could have been created when the page loaded, but I decided to create it only when the user first focuses on the comment textarea. Since the live preview is only an enhancement, and since it is a purely visual enhancement, I don't see any need to have either the extra markup inserted or the jQuery triggered unless someone is actually going to use it.

Fortunately, jQuery has a .one("focus") event handler, which, as the name makes painfully clear, is executed only once:

Unlike a call to the normal .focus() method, calling .one("focus") causes the bound function to be executed only the first time it is triggered, and never again (unless it is re-bound).

Using .one("focus") we can avoid creating multiple live preview DIVs if the user clicks in, then out, then back in the comment textarea.

Here is what the DIV creation code looks like:

 $('#comment').one("focus",function() {
   $(this).parent().after('<div id="preview-box"><div class="comment-by">Live Comment Preview</div><div id="live-preview"></div></div>');
 });

So, the first time an element with an ID of "comment" gets the focus, we move up to this element's parent (<p>) and insert a collection of three DIVs after it. I use a containing DIV (#preview-box) and inside it place a heading DIV (.comment-by) and the important live preview DIV (#live-preview).

Note: I initially created the preview box immediately after the textarea, still within the paragraph, but Internet Explorer 6 did not like that one bit. The preview text wouldn't appear, and I instead got the very helpful JavaScript error: "Unknown runtime error." IE didn't seem to mind the preview box outside the paragraph. Go figure.

Make the Preview DIV Work

Now here comes the really tough part (wink, wink). We're going to make everything inside the comment textarea appear inside the "live-preview" DIV as well, as it is being typed. Unlike the textarea, the live preview will be nicely formatted and show the result of tags such as <strong> and <a href="">, not the tags themselves.

As you might have guessed, jQuery has a bunch of "helper" event functions — keyup, keydown, keypress, etc. — for this type of job. I used keyup:

 $('#comment').keyup(function() {
   $('#live-preview').html( $(this).val() );
 });

Inside the event handler for #comment, $(this) refers to #comment.

Iron Out the Wrinkles

Our live preview works pretty well, just the way it is. The only problem occurs when we hit the Enter key: The preview text stays on the same line.

To fix this little problem, we can use a couple regular expressions. We can start by declaring a variable outside the the keyup function, so it is only done once: var $comment = '' (while the "$" isn't necessary before "comment," it helps me remember that the variable will be storing a jQuery object). Then inside the keyup function, we set the variable to be the value of the comment textarea: $comment = $(this).val().

Finally, we account for the line breaks by using two regular expressions. Since a line break in textareas is read as "\n", we need to replace that with the <br /> tag. If there are two or more line breaks in a row, we'll replace them with two <br /> tags. I realize that it's not properly "semantic," but I think we can get away with it since it's just for preview text that will be discarded anyway. Here are the two "replace" lines:

 $comment = $comment.replace(/\n/g, "<br />")
   .replace(/\n\n+/g, '<br /><br />');

Notice the "/g"? That's a "global" switch to ensure that every occurrence is replaced. (If you want to learn more about regular expressions in JavaScript, tutorials and references abound on the web).

Now we can put $comment — instead of $(this).val() — inside the parentheses of .html().

The Full Code

Here is what the jQuery looks like in its entirety, wrapped inside $(document).ready():

 $(document).ready(function() {
   $('#comment').one("focus", function() {
     $('#comment').parent().after('<div id="preview-box"><div class="comment-by">Live Comment Preview</div><div id="live-preview"></div></div>');
   });
   
   var $comment = ''; // that's two single quotation-marks at the end
   $('#comment').keyup(function() {
     $comment = $(this).val();
     $comment = $comment.replace(/\n/g, "<br />")
       .replace(/\n\n+/g, '<br /><br />');
     $('#live-preview').html( $comment );
   });
 });

That's all there is to it. Successfully tested in Firefox 1.5 - 2.0, Safari 2.0.4, and Internet Explorer 6. As I suggested earlier, it almost seems too easy to be real.

To test my implementation of this code yourself, just post a comment to this entry. I'd love to hear from you anyway. Comment moderation is turned on for anyone who has not previously posted an approved comment. I'm happy to approve comments, even if they only say "testing, testing, this is great!" However, if you want to test submitting a comment with the Live Preview, but you don't care if it is actually published, just type "don't publish" or "don't approve" or something to that effect in the comment so I know to delete it. Thanks!