Plugin: Sexy Comments v1.4 Released!

August 3, 2007 | 201 Comments

Introduction

This has been a long time coming and I am happy to announce the release of Sexy Comments v1.4! With this version comes a lot of changes...so be sure to read the installation section! Along with simple optimizations and general restructure, the following features are now available:

Feature List

  • Ajax comment preview (new feature)
  • Author post highlighting
  • Avatars
    • Either display/hide avatars
    • Select your avatar service of choice (Gravatar and MyBlogLog options are available)
    • Specify maximum avatar dimension (Gravatar Only)
    • Customize default/trackback avatars
  • Comment Reply-To (new feature)
  • Comment Themes (new feature)
  • CSS overriding
  • "Number of Comments" message customization
  • jQuery inclusion toggling

Installation & Upgrading

  1. Download Sexy Comments v1.4 from the WordPress plugin directory
  2. Unzip that little sucker
  3. Place sexy-comments folder in your wp-content/plugins directory (it should look like this: wp-content/plugins/sexy-comments/
  4. Log in to your WordPress plugin admin page and activate the plugin.
  5. In the plugin admin page, click the SexyComments sub-menu.
  6. Customize the settings until you have something that works for you.
  7. Locate your theme's template file that displays comments (typically comments.php). Remove the comment output loop and replace with:
    PHP:
    1. <?php sexycomments::show($comments); ?>

  8. If you plan to use the Ajax features or the Reply-To features, you will need to do two things.
    1. Enable jQuery and jQuery Form Extension via the Plugin > SexyComments administration page.
    2. Locate the template file that contains the comment submission form (typically comments.php near the bottom) and replace that chunk of code with:
      PHP:
      1. <?php sexycomments::form(); ?>

    NOTE: Be sure not to touch the section that generates the form for adding comments! This plugin does not re-create the comment creation form.

  9. Lastly, consider disabling the plugin CSS and taking the example CSS provided and customize it to suit your theme's color scheme.
  10. You should be all set, now! w00t w00t! Go make a MyBlogLog or Gravatar account if you don't already have one and upload an avatar. Gravatar tends to be pretty flakey so I'd suggest using MyBlogLog.

FAQs

  • Q: What is this "comment loop" you speak of?

    A: Ah, yes. That thing. Well, its anatomy looks similar to this (there will be some variation from theme to theme):

    PHP:
    1. <?php if ($comments) : ?>
    2.     <!-- some HTML is typically here -->
    3.  
    4.     <?php foreach ($comments as $comment) : ?>
    5.         <!-- the output HTML of each individual comment -->
    6.  
    7.     <?php endforeach; /* end for each comment */ ?>
    8.     <!--...more HTML -->
    9.  <?php else : // this is displayed if there are no comments so far ?>
    10.     <?php if ('open' == $post->comment_status) : ?>
    11.         <!-- typically a blank area or a place with a comment -->
    12.      <?php else : // comments are closed ?>
    13.         <!-- closed comments section -->
    14.     <?php endif; ?>
    15. <?php endif; ?>

  • Q: Ok...so I just upgraded to a new version and there is nothing in the SexyComments admin page...WTF?

    A: Yeah. Sorry about that. In this version, the directory structure has changed drastically and Sexy Comments should no longer live in wp-content/plugins/sexycomments.php OR wp-content/plugins/sexycomments/sexycomments.php, but instead it should be in wp-content/plugins/sexy-comments/. Make sure that the plugin is in the correct location of your plugins directory.

  • Q: What happened to sexycomments_print($comments)? I used to use that to get my comments to display...will it still work?

    A: Along with a directory structure overhaul, this version had a large code overhaul as well. The old function (sexycomments_print) is deprecated but will still work for the time being. I greatly urge you to move over to the new function call sexycomments::show($comments) as that is the new *impoved* function.

WordPress Plugin: Sexy Comments

April 5, 2007 | 76 Comments

Unhappy with my theme's comment display, I recently re-coded a sexier comment display as a plugin so others can sexify their comments as well.

Download the plugin.

Features

  • Forum-thread-like comment layout: User information to the left, comment to the right.
  • Author post highlighting
  • Altered Trackback/Pingback Display Formating
  • Avatars
    • Either display/hide avatars
    • Select your avatar service of choice (Gravatar is the only option until I find more avatar services)
    • Specify maximum avatar dimension
    • Customize default/trackback avatars
  • "Number of Comments" Message Customization
  • CSS Overriding

Installation

  1. Download and unzip the sexycomments.zip
  2. Place sexycomments folder in your wp-content/plugins directory
  3. Log in to your WordPress admin panel and activate the plugin, then visit the SexyComments submenu of the plugins tab.
  4. Customize the settings until you have something that works for you.
  5. Locate the template file(s) in your theme that loops over and displays comments. Remove that comment output loop and replace with:
    PHP:
    1. <?php sexycomments_print($comments); ?>

    NOTE: Be sure not to touch the section that generates the form for adding comments! This plugin does not re-create the comment creation form.

  6. Lastly, consider disabling the plugin CSS and taking the example CSS provided and customize it to suit your theme's color scheme.
  7. You should be all set, now! w00t w00t! Go make a Gravatar account if you don't already have one and upload an avatar.

Sweet Image Manipulation: OH NOES!

February 12, 2007 | 4 Comments

yikes_oh_noes

Thank you. That is all.

The Ajax Experience

October 10, 2006 | 5 Comments

Well, it seems my application for one of the 5 scholarships to The Ajax Experience has gotten through! w00t!

The Ajax Experience is:

Ajaxian and NoFluffJustStuff Java Symposiums (NFJS) are pleased to announce The Ajax Experience 2006 Fall Edition - Boston. We had a great time at the spring event in San Francisco, so we decided to do another show on the east coast. This international event will take place October 23 - 25, 2006 at the brand new Westin Boston Waterfront in Boston, Massachusetts.

The Ajax Experience 2006: Boston show will feature sixty (60) technically focused ninety (90) minute sessions across three (3) full days spanning six (6) parallel tracks with over (40) forty speakers.

We encourage you to register as soon as possible because seating is limited and we anticipate a sold out show. Here is your opportunity to attend one event where you will find authors and industry notables in one place for the duration of The Ajax Experience Fall 2006 show. This is a unique event you should want to be a part of.

When I first heard about the conference last year, I was extremely excited...but had my hopes stomped when I brought the cost to my manager. Ajax was "too new" and the University could not justify the expense of the trip. I waited a year and once again had the eyebrow raised when I brought it up. Not necessarily my manager's fault...but convincing the University System that they should do something is like convincing a rock it should get up and walk around.

When I saw the Scholarship Program for The Ajax Experience, I got to typing and sent in my application with crossed fingers and high hopes. My typing paid off. Here's what I wrote:

My name is Matthew Batchelder, I run BorkWeb ( http://borkweb.com), am a co-founder of MasterWish (http://masterwish.com), and am a web application developer at Plymouth State University (PSU) in Plymouth, NH. I'm close by yet so far away.

A few PSU co-workers and I have been steering web development at the university to include Ajax techniques to enhance the speed and usability of our applications on campus. Users have been pleased with the results and want more! But...PSU - being a state-run university - lacks funds to send all of their employees to conferences, especially conferences where the higher-ups [don't know] what valuable information can be attained there - brains, networking, tips, etc. When mentioning this conference both last year and this year, I've been met with a handfull of negative responses: "No, we don't have the resources" to "Ajax...isn't that a cleaning product?."

MasterWish - a one and a half year old brainchild of a couple of other developers and myself - has been my playground after work hours. I began my experimentation with Ajax using that site, as PSU tended to slap my hand when looking into Ajax at work. Through that experimentation, I began to understand the workings of Ajax and how it would work into the PHP/Templating environment I was so comfortable with. Once I had dug down, I promptly posted my "Ajax; Templating; and the Separation of Layout and Logic" article that Ajaxian blogged about, along with the follow-up article.

I am building. I am reading. I am experimenting. I am writing. There's always more to learn and I'd love to see and hear what the Ajax leaders are doing to help guide my train of thought. Re-creating the wheel sucks and conferences are a great way to have a lot of information slammed into your skull and an even better way to network. Sadly, the price of The Ajax Experience admission is too great great a cost for me to fund myself, and PSU [doesn't always] know what's best for them and refuse to pay. I look to you for help.

Thank you for your consideration. If you need anything more from me, please let me know!
-Matt

I look forward to picking brains, networking, sucking in as much information as I can get, and blogging it all :D So: I owe a HUGE thanks to the guys over at Ajaxian; and a big congrats to the other 4 that received a scholarship. I'll see you all there!

Oh....and I look forward to the swag:

  • All Access Pass - The Ajax Experience
  • Branded iPOD Shuffle - The Ajax Experience
  • Two free books - Ajax Design Patterns & Java Script: The
    Definitive Guide, 5E
  • Free Access to Slides/Audio of The Ajax Experience 2006: San
    Francisco ($250 Value!!)
  • Custom Laptop Bags - The Ajax Experience
  • The Ajax Experience Shirt
  • The Ajax Experience Binder with handouts from sessions attended
  • CD with all presentations
  • Slides/audio/select videos of The Ajax Experience: Boston
  • Breakfast, Lunch, Dinner, Breaks
  • The Ajax Experience Party
  • Great Giveaways including iPOD Nanos, iPOD Videos and XBOX 360s

Remote JavaScripting Example - Part I

September 22, 2006 | 5 Comments

At Plymouth State we work in a multi-server environment and often wish to display dynamic content from one server in an Ajax-like fashion on another server's website. My co-worker, Zach Tirrell, and I have drummed up a solution that works to keep our layout and logic separate, while still serving our end users in a smooth, seamless, non-iFramed manner.

I'll walk through the creation of a simple search 'widget' that relies on dynamic data to populate a drop-down box.

The Tools

- PHP
- JavaScript
- XTemplate
- RemoteJSOutput: a simple script by Matthew Batchelder (me) and Zach Tirrell

Step 1: create your template

This widget is fairly simple and thus has a simple template. The template syntax is simply XTemplate syntax.

I'll name it widget.tpl and store it in a templates directory.

HTML:
  1. <!-- BEGIN: main -->
  2. <div id="sweet_borkweb_widget" style="background:#eee;border:1px solid #ccc;text-align:center;">
  3.   <div style="color:#000;">A Couple JavaScript Posts at BorkWeb</div>
  4.   <select id="borkweb_posts">
  5.     <option value=""></option>
  6.   <!-- BEGIN: post -->
  7.     <option value="{post.url}">{post.title}</option>
  8.   <!-- END: post -->
  9.   </select>
  10. </div>
  11. <!-- END: main -->

Step 2: simple template output

First we'll just spit out the template. Lets create a PHP file to do this. We'll call it widget.php

PHP:
  1. <?php
  2. include('includes/xtemplate.php');
  3. $xtpl = new XTemplate('templates/widget.tpl');
  4.  
  5. $xtpl->parse('main');
  6. $xtpl->out('main');
  7. ?>

Check out your widget so far. Its plain. Lets change that.

Step 3: add dynamic content

We want the drop down list to hold BorkWeb articles. We'll add that in now.

Note: this is where you would normally pull from a database, an RSS feed, or some other source. For simplicty, we'll be using a simple PHP array. Whoop-de-doo. Here it is:

PHP:
  1. <?php
  2. include('includes/xtemplate.php');
  3. $xtpl = new XTemplate('templates/widget.tpl');
  4.  
  5. //get list of articles
  6. $articles=array(
  7.   array('title'=>'Ajax, More Than A Buzz Word','url'=>'http://borkweb.com/story/ajax-more-than-a-buzz-word'),
  8.   array('title'=>'Ajax; Templating; and the Separation of Layout and Logic','url'=>'http://borkweb.com/story/ajax-templating-and-the-separation-of-layout-and-logic'),
  9.   array('title'=>'Deleting the Internet','url'=>'http://borkweb.com/story/deleting-the-internet'),
  10.   array('title'=>'Node Manipulation in the DOM','url'=>'http://borkweb.com/story/node-manipulation-in-the-dom'),
  11.   array('title'=>'Prototype Cheat Sheets','url'=>'http://borkweb.com/story/prototype-cheat-sheets'),
  12.   array('title'=>'Script.aculo.us Is My New Best Friend','url'=>'http://borkweb.com/story/scriptaculous-is-my-new-best-friend'),
  13.   array('title'=>'The Case For JSON: What Is It and Why Use It?','url'=>'http://borkweb.com/story/the-case-for-json-what-is-it-and-why-use-it')
  14. );
  15.  
  16. //loop over articles and place in template
  17. foreach($articles as $article)
  18. {
  19.   $xtpl->assign('post',$article);
  20.   $xtpl->parse('main.post');
  21. }//end foreach
  22.  
  23. $xtpl->parse('main');
  24. $xtpl->out('main');
  25. ?>

Check out your widget now. It has been populated with some data! w00t! Now to make it work, we return to our beloved widget.tpl template file.

Step 4: make the template work

We're going to add in some javascript. Lets make the dropdown list redirect the user to the selected article when the drop-down box changes.

I'm going to add this on our select box:

HTML:
  1. onchange="if(document.getElementById('borkweb_posts').value!='') document.location=document.getElementById('borkweb_posts').value;"

The template should now look like this:

HTML:
  1. <!-- BEGIN: main -->
  2. <div id="sweet_borkweb_widget" style="background:#eee;border:1px solid #ccc;text-align:center;">
  3.   <div style="color:#000;">A Couple JavaScript Posts at BorkWeb</div>
  4.   <select id="borkweb_posts" onchange="if(document.getElementById('borkweb_posts').value!='') document.location=document.getElementById('borkweb_posts').value;">
  5.     <option value=""></option>
  6.   <!-- BEGIN: post -->
  7.     <option value="{post.url}">{post.title}</option>
  8.   <!-- END: post -->
  9.   </select>
  10. </div>
  11. <!-- END: main -->

Step 5: prepare script for remoting

Now that our lovely widget is functioning, lets prepare it for inclusion in other locations. This is simple using RemoteJSOutput (a simple script written by Zach Tirrell and myself).

We'll include that PHP class and use it as follows:

PHP:
  1. <?php
  2. include('includes/RemoteJSOutput.class.php');
  3. $remoteOutput=new RemoteJSOutput();
  4.  
  5. //start output buffering via
  6. $remoteOutput->start();
  7.  
  8. include('includes/xtemplate.php');
  9. $xtpl = new XTemplate('templates/widget.tpl');
  10.  
  11. //get list of articles
  12. $articles=array(
  13.   array('title'=>'Ajax, More Than A Buzz Word','url'=>'http://borkweb.com/story/ajax-more-than-a-buzz-word'),
  14.   array('title'=>'Ajax; Templating; and the Separation of Layout and Logic','url'=>'http://borkweb.com/story/ajax-templating-and-the-separation-of-layout-and-logic'),
  15.   array('title'=>'Deleting the Internet','url'=>'http://borkweb.com/story/deleting-the-internet'),
  16.   array('title'=>'Node Manipulation in the DOM','url'=>'http://borkweb.com/story/node-manipulation-in-the-dom'),
  17.   array('title'=>'Prototype Cheat Sheets','url'=>'http://borkweb.com/story/prototype-cheat-sheets'),
  18.   array('title'=>'Script.aculo.us Is My New Best Friend','url'=>'http://borkweb.com/story/scriptaculous-is-my-new-best-friend'),
  19.   array('title'=>'The Case For JSON: What Is It and Why Use It?','url'=>'http://borkweb.com/story/the-case-for-json-what-is-it-and-why-use-it')
  20. );
  21.  
  22. //loop over articles and place in template
  23. foreach($articles as $article)
  24. {
  25.   $xtpl->assign('post',$article);
  26.   $xtpl->parse('main.post');
  27. }//end foreach
  28.  
  29. $xtpl->parse('main');
  30. $xtpl->out('main');
  31.  
  32. //spit out script encased in JS
  33. $remoteOutput->puke();
  34. ?>

Now check out your widget. Ugly, huh? Well, don't worry, thats the way its supposed to look for now.

Step 6: place your widget somewhere

Now that we have that beautiful chunk of code in operation, place it on a webpage somewhere.

Put this:

HTML:
  1. <script type="text/javascript" src="http://url.to/your/widget.php"></script>

on any page you wish to test your widget!

Optional Step 7: create a wrapper

If, like me, you aren't a fan of including RemoteJSOutput.class.php all over hell's half acre, you can create a wrapper. This not only allows you to minimize the code you have to repeatedly place everywhere, but it also keeps your widget.php script functional on its own!

Here's an example wrapper I'll call get_script.php which will display wrapper_widget.php (step 3's PHP file, renamed):

PHP:
  1. <?php
  2. include('includes/RemoteJSOutput.class.php');
  3. $remoteOutput=new RemoteJSOutput();
  4.  
  5. //start output buffering via
  6. $remoteOutput->start();
  7.  
  8. //create a list of allowable widgets/scripts/yadda yadda
  9. $allow=array('wrapper_widget');
  10.  
  11. //does the passed variable exist in the allowable widgets?
  12. if(in_array($_GET['script'],$allow))
  13. {
  14.   //include the wrapper
  15.   include($_GET['script'].'.php');
  16. }//end if
  17.  
  18. //spit out script encased in JS
  19. $remoteOutput->puke();
  20. ?>

So rather than using the script tag that Step 6 suggests, we'd use:

HTML:
  1. <script type="text/javascript" src="http://url.to/your/get_script.php?script=wrapper_widget"></script>

Conclusion

This method is simplistic and is simply touching on the topic of widgetization. I will be following up with dynamic user interactions in Part II, and finally discuss an open-standard widget library with xml definitions. Stay tuned :)

Download

Oh, and here's the code used in this tutorial all zipped up.

Finally. A Cool Looking Human Clone.

May 16, 2006 | 6 Comments

After the success of cloning Dolly The Sheep, I am pleased to announce that scientists have finally perfected the Human clone. Check out the perfection as my clones check my tomato-mushroom-and-basil quiche, fetch me a cup of water, put bread in the breadbox, and place utensils in the dishwasher...all while I snapped their photo. All I can say is that my wife is one happy woman. Here are my clones:

Cloning

Writing Your Server-Side Ajax Handler

March 22, 2006 | 19 Comments

In my recent post on 'Ajax; Templating; and the Separation of Layout and Logic,' I refer to an Ajax Handler that sits server side to handle Ajax calls. Some elaboration is in order.

As I have stated in the past, I'm a huge fan of Prototype AND I choose PHP as my language of choice...so my examples will be using both, but the idea is portable.

Set up your Functions

Before you create a handler, you need a set of functions that the handler can reference. Here's an example:

PHP:
  1. <?php
  2. function world($params='')
  3. {
  4.   return 'Goodbye Cruel World.';
  5. }//end world
  6.  
  7. function sweetWorldAction($params='')
  8. {
  9.   //we expect params to be an array or a string similar to a parameter string from a GET..i.e. "bork=asdf&cheese=yes please"
  10.   //parse out the variables
  11.   if(!is_array($params))
  12.   {
  13.     parse_str($params,$params);
  14.   }//end if
  15.  
  16.   //do your logic here
  17. }//end sweetWorldAction
  18. ?>

Now that we have the functions all set, we'll set up a handler that receives Ajax calls and calls the appropriate functions.

The Eval Method - A Dynamic Handler

This method is one that I toyed around with for a while and I'll admit that its pretty simple and clean but there are some drawbacks. We're going to make a few assumptions: All requests will be GET (this is to keep things simple for this example) and we will keep the complexity of .htaccess sweetness out of these examples and assume that each call will be passing a function variable that specifies the function we are calling. I'll get to those in a second...but first I'll show you the handler code in this Eval Method:

PHP:
  1. <?php
  2. //if the user leaves the page or closes the browser prematurely, this will help prevent half completed statements
  3.  
  4. include('functions.php');
  5.  
  6. //list out your Ajax accessible functions
  7. $valid_functions = array('world','sweetWorldAction');
  8.  
  9. if($_GET['function'] && in_array($_GET['function'],$valid_functions))
  10. {
  11.   //get the get parameters
  12.   $params = $_GET
  13.   //unset the function index from the params because we just don't need it there
  14.   unset($params['function']);
  15.  
  16.   //build your parameter string:
  17.   $param_string='';
  18.   foreach($params as $key=>$param)
  19.   {
  20.     $param_string.=(($param_string)?'&':'').$key.'='.$param;
  21.   }//end foreach
  22.  
  23.   //make your function call
  24.   eval($_GET['function']."('$param_string');");
  25. }//end if
  26.  
  27. ?>

The Variable Variable Method - A Dynamic Handler

This method (compliments of PHPDeveloper) is simpler than the Eval Method and just as dynamic.

PHP:
  1. <?php
  2. //if the user leaves the page or closes the browser prematurely, this will help prevent half completed statements
  3.  
  4. include('functions.php');
  5.  
  6. //list out your Ajax accessible functions
  7. $valid_functions = array('world','sweetWorldAction');
  8.  
  9. if($_GET['function'] && in_array($_GET['function'],$valid_functions))
  10. {
  11.   //get the get parameters
  12.   $params = $_GET
  13.   //unset the function index from the params because we just don't need it there
  14.   unset($params['function']);
  15.   //make your function call
  16.   $_GET['function']($params);
  17. }//end if
  18.  
  19. ?>

The Switch Method - A Basic Handler

This method handles each call individually. The reason for using switch rather than if-elses is simply because your application will most likely possess a large number of Ajax-ified functions and those if-elses would be ghastly to read and decrease performance...the Switch statement is much cleaner.

PHP:
  1. <?php
  2. //if the user leaves the page or closes the browser prematurely, this will help prevent half completed statements
  3.  
  4. include('functions.php');
  5.  
  6. if($_GET['function'])
  7. {
  8.   switch $_GET['function']
  9.   {
  10.     case 'world':
  11.       echo world();
  12.       exit;
  13.     break;
  14.     case 'sweetWorldAction':
  15.       echo sweetWorldAction();
  16.       exit;
  17.     break;
  18.   }//end switch
  19. }//end if
  20.  
  21. ?>

Make a Choice

Which are you going to use? While the Eval and Variable Variable Methods contain very small amounts of code in the handlers, the logic has simply been shifted to the functions themselves. Increased Ajax-geared logic within the functions themselves reduces portability. However, in the Switch Method, logic is organized in a fairly easy to follow manner while making use of very generic functions that can be used in multiple fashions. Obviously, the Switch Method is my preferred choice :)

In Closing

Handler scripts make the Ajax magic happen and the separation of handler logic from your application logic is just as important for robust development and debugging as the need for separation of layout and logic. Play around with the above methods and see which works for you. If you have a method all your own, I'd be interested to hear it!

Ajax; Templating; and the Separation of Layout and Logic

March 10, 2006 | 141 Comments

The Background

I have often mentioned my process of expanding my proficiency of Ajax. Through my journey I have made a number of wrong turns and hit my share of stumbling blocks. All of that has been a learning experience and I'm learning still. I began fiddling with XMLHttpRequest as many do - blissfully ignorant of the many frameworks that exist to make Ajax super easy. My code was bloated with some neat...'features' (pronounced: bugs).

Then I discovered the Simple Ajax Toolkit (SAJAX), which was simpler than doing raw XMLHttpRequest but really not all that simple. My latest step into the world of Ajax, and the toolkit that holds my love (currently) is Prototype...and I like my Prototype served with a side of Script.aculo.us. *drool* UPDATE: I now use jQuery for all my Ajax and DOM manipulation goodness.

While Ajax is the cause for the article, the heavy focus is on templating. For the past few years I have been using XTemplate as my templating library (I'm a PHP buff) and have been happily separating my logic from my layout...unitl I ran smack dab into the power of Javascript. My PHP still kept its separation from HTML as is the purpose of XTemplate, but it was my HTML that became littered with little nuggets of Javascript all over the place. No matter the method to my Ajax madness, this was my problem.

What Exactly Is Templating And Why Do It?

Templating is definately not new and its use has been debated back and forth for quite some time. But like I stated above, the goal of templating is to keep logic separate from layout which is a good thing for a couple of reasons:

  1. Less clutter. Face it, HTML and whatever server-side scripting language you choose to use are two different beasts. Mixing them together is visually unappealing making code hard to read...and hard to read code is hard to debug.
  2. Coders can develop code. Designers can develop layout. With templating, you are able to achieve this separation and avoid the need for a developer to butcher a designer's layout to make it function with an application. Each can design/code on their own then combine their efforts with ease.
  3. With separation such as this, applications are more easily skinned and/or receptive to complete UI overhauls.
  4. Did I mention less clutter?

Let me give you an example of what I mean with a simple Goodbye Cruel World application:

Here's the PHP script: goodbye.php

PHP:
<