darrinb http://darrinb.com Professional WordPress development since 2006 Sat, 21 May 2016 18:38:44 +0000 en-US hourly 1 Easy Banners Widget http://darrinb.com/easy-banners-widget/ http://darrinb.com/easy-banners-widget/#respond Wed, 27 Apr 2016 19:37:35 +0000 http://darrinb.com/?p=1564 Grab your visitors' attention with the new Easy Banners Widget. This plugin is an easy-to-use WordPress widget that allows you to configure and display call-to-action banners in your site's sidebars.

The post Easy Banners Widget appeared first on darrinb.

]]>
With the Easy Banners plugin you can create an unlimited number of eye-catching banners and display them in your site’s sidebars. The Easy Banners Widget is a straight-forward WordPress plugin that makes building call-to-action banners a breeze!

Use them for limited-time offers, announcements, ads, donation links, etc.; the possibilities are endless. And with the built-in color picker and preview functionality, you can easily tailor the look of each banner to match your site’s styles.

Features

  • Configurable widget title.
  • Easily select banner color using built-in color picker.
  • Include html in your banners message.
  • Easily select text color using built-in color picker.
  • Easily link the banners to any url.
  • Choose the default (basic) CSS styling or roll your own.

Screenshots

preview color your combos
preview color your combos
default styling
default styling
custom styling
custom styling

Installation

As of this writing, the plugin is awaiting review by the plugin team at the WordPress.org repository, but in the meantime, you can download and install off of GitHub. Just follow the instructions below.

From GitHub:

  1. Download the latest stable version.
  2. Extract the zip folder to your plugins directory.
  3. Activate in the “Plugins” area of your admin by clicking the “Activate” link.
  4. No further setup or configuration is necessary; just head over to your Widgets area to add to your sidebar.

Usage

Using it out of the box is really straight-forward. The Easy Banners Widget functions like any other widget for WordPress. You can either configure one it through the Widgets screen in your WordPress Dashboard (Appearance > Widgets) or through your the Customizer (Appearance > Customizer).

Note: Unlike the default widgets that come pre-installed with WordPress, the Easy Banners Widget assigns unique IDs to each widget created. So feel free to create as many banners with as many configurations as you’d like!

The post Easy Banners Widget appeared first on darrinb.

]]>
http://darrinb.com/easy-banners-widget/feed/ 0
Advanced Categories Widget http://darrinb.com/advanced-categories-widget/ http://darrinb.com/advanced-categories-widget/#respond Sun, 24 Apr 2016 16:41:16 +0000 http://darrinb.com/?p=1556 Display your categories in style with the new Advanced Categories Widget! This categories widget gives you enhanced features for customizing your site's categories list.

The post Advanced Categories Widget appeared first on darrinb.

]]>
Build a better category list.

The Advanced Categories Widget is a powerful and flexible category widget for WordPress that makes building and displaying custom category lists a snap.

Organize your site in style with this highly customizable category widget!

Features

  • Build multiple lists!
  • Select which categories to display.
  • Choose how to order your categories: name, post count, etc.
  • Set the order for displaying the categories.
  • Supports category thumbnails.
  • Set and preview custom thumbnail sizes, or choose from your site’s registered image sizes.
  • Show a description of each category.
  • Set and preview the length of the description.
  • Select the list format to match your site’s markup. Choose from: ol, ul, or div.
  • Show post count.
  • Choose the default (basic) CSS styling or roll your own.

Multiple Lists Support

Do you have a lot of categories? Do you want to highlight different categories in different sections of your site? With the Advanced Categories Widget, you can easily create more than just a boring categories list.

advanced-categories-widget-filter-settings

Custom Thumbnail Sizes

With the Advanced Categories Widget, you can set and preview a custom thumbnail size to display in your sidebar. Already have the perfect size thumbnail? The widget also detects all registered images sizes and creates an easy way to choose which to display. And with WordPress 4.4, responsive images are natively supported using built-in core functionality.

advanced-categories-widget-thumbnail-preview

Note: The Advanced Categories Widget is compatible with the Advanced Term Images plugin for displaying featured images for categories.

Custom Category Descriptions

Draw your readers in by displaying a brief description of each category in your list. The Advanced Categories Widget provides an easy way to set the length of the excerpts that will appear. And with a handy preview feature, you can see a sample excerpt set to the length you choose, before saving your settings.

advanced-categories-widget-description-preview

Default CSS Styles

The Advanced Categories Widget comes installed with a default stylesheet option to get you going. The styling is based on the twentysixteen core theme. Selecting the Default Styles option will give you a quick start to styling your categories list. For more control over the look and feel of your list, the widget also has a number of classes available to further customize its appearance to match your theme.

advanced-categories-widget-layout-settings

The Resulting List

With a little bit of styling (to keep it in-style with your site) the resulting list can look similar to this:

categories-list

Installation

As of this writing, the plugin is awaiting review by the plugin team at the WordPress.org repository, but in the meantime, you can download and install off of GitHub. Just follow the instructions below.

From GitHub:

  1. Download the latest stable version.
  2. Extract the zip folder to your plugins directory.
  3. Activate in the “Plugins” area of your admin by clicking the “Activate” link.
  4. No further setup or configuration is necessary; just head over to your Widgets area to add to your sidebar.

Usage

Using it out of the box is really straight-forward. The Advanced Categories Widget functions like any other widget for WordPress. You can either configure one it through the Widgets screen in your WordPress Dashboard (Appearance > Widgets) or through your the Customizer (Appearance > Customizer).

Note: Unlike the default Categories widget that comes pre-installed with WordPress, the Advanced Categories Widget assigns unique IDs to each list created. So feel free to create as many category lists with as many configurations as you’d like!

The post Advanced Categories Widget appeared first on darrinb.

]]>
http://darrinb.com/advanced-categories-widget/feed/ 0
Advanced Posts Widget http://darrinb.com/advanced-posts-widget/ http://darrinb.com/advanced-posts-widget/#comments Sat, 09 Apr 2016 23:31:04 +0000 http://darrinb.com/?p=1535 Make your recent posts pop with the new Advanced Posts Widget! This recent posts widget gives you enhanced features for customizing your recent posts lists.

The post Advanced Posts Widget appeared first on darrinb.

]]>
Build a better post list.

The Advanced Posts Widget is a powerful and flexible recent posts widget for WordPress that makes building and displaying customized content lists a snap. Supports all custom post types and taxonomies!

Make your post lists stand out with this highly customizable recent posts widget!

Features

  • Build multiple lists!
  • Select which post types to display. (You can choose either all types, or a specific type.)
  • Set the number of posts to show.
  • Choose how to order your posts: publish date, alphabetically, random, etc.
  • Set the order for displaying the posts.
  • Filter by category, tag, or custom taxonomy.
  • Supports post thumbnails.
  • Set and preview custom thumbnail sizes, or choose from your site’s registered image sizes.
  • Show an excerpt of the post.
  • Set and preview the length of the excerpt.
  • Select the list format to match your site’s markup. Choose from: ol, ul, or div.
  • Select the listing format. Choose between html5 or xhtml.
  • Show post date.
  • Set and preview multiple date formats.
  • Choose the default (basic) CSS styling or roll your own.

Multiple Lists Support

Do you have multiple content types to share? Do you want to highlight different categories of posts? With the Advanced Post Widget, you can easily create more than just a boring “recent posts” list. Create one list for your recent News, one for recent blog posts, and one to highlight a certain category! All post types and taxonomies supported.

Custom Post Types

advanced-posts-widget-posttype-option_thumb

Have more than just blog posts to share? The Advanced Posts Widget automatically detects all your registered public post types, giving you an easy way to select which type to create a list for.

Custom Taxonomies

Gone are the days of just categories and tags. With custom post types comes custom taxonomies. The Advanced Posts Widget automatically detects all registered taxonomies and builds settings for each in the widget options form.

advanced-posts-widget-filter-settings

Custom Thumbnail Sizes

With the Advanced Posts Widget, you can set and preview a custom thumbnail size to display in your sidebar. Already have the perfect size thumbnail? The widget also detects all registered images sizes and creates an easy way to choose which to display. And with WordPress 4.4, responsive images are natively supported using built-in functionality.

preview-thumbnail-2

Custom Post Excerpts

Draw your readers in by displaying a brief excerpt of each post in your list. The Advanced Post Widget provides an easy way to set the length of the excerpts that will appear. And with a handy preview feature, you can see a sample excerpt set to the length you choose, before saving your settings.

preview-excerpt

Native Formatting

The Advanced Posts Widget automatically detects your theme’s support for html5 and will set your list settings accordingly. Once saved, the widget will generate a semantically-correct html5 article list of your posts. You can also choose the more generic html version if you’d prefer.

advanced-posts-widget-format-settings_2

Date Formatting

The Advanced Posts Widget even has the option to set and preview the publish date for the posts, should you choose to display it. Easily choose from among 4 popular date formats.

advanced-posts-widget-date-format-settings

Default CSS Styles

The Advanced Posts Widget comes installed with a default stylesheet option to get you going. The styling is based on the twentysixteen core theme. Selecting the Default Styles option will give you a quick start to styling your posts list. For more control over the look and feel of your list, the widget also has a number of classes available to further customize its appearance to match your theme.

advanced-posts-widget-layout-settings

The Resulting List

With a little bit of styling (to keep it in-style with your site) the resulting list can look similar to this:

posts-list

Installation

As of this writing, the plugin is awaiting review by the plugin team at the WordPress.org repository, but in the meantime, you can download and install off of GitHub. Just follow the instructions below.

Update April 11, 2016: The plugin has been approved by the Review Team and is now available on the WordPress plugin repository: https://wordpress.org/plugins/advanced-posts-widget/

From the WordPress.org plugin repository:

  1. Download and install using the built in WordPress plugin installer.
  2. Activate in the “Plugins” area of your admin by clicking the “Activate” link.
  3. No further setup or configuration is necessary; just head over to your Widgets area to add to your sidebar.

From GitHub:

  1. Download the latest stable version.
  2. Extract the zip folder to your plugins directory.
  3. Activate in the “Plugins” area of your admin by clicking the “Activate” link.
  4. No further setup or configuration is necessary; just head over to your Widgets area to add to your sidebar.

Usage

Using it out of the box is really straight-forward. The Advanced Posts Widget functions like any other widget for WordPress. You can either configure one it through the Widgets screen in your WordPress Dashboard (Appearance > Widgets) or through your the Customizer (Appearance > Customizer).

Note: Unlike the default Recent Posts widget that comes pre-installed with WordPress, the Advanced Posts Widget assigns unique IDs to each list created. So feel free to create as many comment lists with as many configurations as you’d like!

The post Advanced Posts Widget appeared first on darrinb.

]]>
http://darrinb.com/advanced-posts-widget/feed/ 2
Checking for Comment Support on Post Types http://darrinb.com/checking-comment-support-post-types/ http://darrinb.com/checking-comment-support-post-types/#respond Wed, 30 Mar 2016 01:06:48 +0000 http://darrinb.com/?p=1279 In the following overview we'll go over determining if a post type supports comments, and how to build this functionality into your plugins.

The post Checking for Comment Support on Post Types appeared first on darrinb.

]]>
When building plugins and custom themes, I always build with the end-user in mind. And while the majority of articles on my site are geared toward other WordPress developers, the majority of my plugins are built to be intuitive for persons not familiar with the inner workings of WordPress. I always try to look at every aspect of the plugin from the eyes of a user who just wants it work. And that means planning and building it out with the smallest details in mind.

My latest plugin, the Advanced Comments Widget, has an option for users to select which post type to display comments for. My reasoning was, they could have difference comment lists in different sections of their site if they wanted.

For example, they could have a recent comments list on their post pages that shows comments on posts only, and a separate comment list on an article page that shows recent comments on their articles. On general pages, they can have either multiple comment lists broken down by post type, or one recent comment list based on all post types.

This ability to select which post type to pull comments on is pretty popular, kind of common sense, and built-in to a few of the other recent comments widgets I saw while doing my research. It’s pretty straight-forward to offer this option; you get all registered public post types, loop through them, and build a select drop down for the widget’s form. The issue I saw was that none of these other widgets checked to see if comments were supported.

I’ll admit, when I first rolled the plugin that builds the widget, I didn’t think of it either. But then it hit me while I was working on a client project. They have multiple custom post types registered for their site; restaurants, shops, events, etc., but comments are not enabled on all of them because it doesn’t make sense for some of them. So why provide that option in the drop down? It just leads to poor UX for the person managing the site and additional overhead on the part of the comment query to include post types that can never have comments. So I updated the method that pulls the post types to display in the widget.

Here’s the method:

/**
 * Retrieves public post types
 *
 * Only returns post types that have comments enabled.
 * Use 'acw_widget_post_type_args' to filter arguments for retrieving post types.
 * Use 'acw_allowed_post_types' to filter post types that can be selected in the widget.
 *
 * @access public
 *
 * @since 1.0
 *
 * @return array $_ptypes Filtered array of post types.
 */
public static function get_post_types()
{
    $post_type_args = apply_filters( 'acw_widget_post_type_args', array( 'public' => true) );
    $post_types = get_post_types( $post_type_args, 'objects' );

    $_ptypes = array();
    $_ptypes['all'] = __('All');

    foreach( $post_types as $post_type ){
        if ( post_type_supports( $post_type->name, 'comments' ) ) {
            $query_var = ( ! $post_type->query_var ) ? $post_type->name : $post_type->query_var ;
            $label = $post_type->labels->singular_name;
            $_ptypes[ $query_var ] = $label;
        }
    }

    $_ptypes = apply_filters( 'acw_allowed_post_types', $_ptypes );
    $_ptypes = ( ! is_array( $_ptypes ) ) ? (array) $_ptypes : $_ptypes ;

    // Clean the values (since it can be filtered by other plugins)
    $_ptypes = array_map('esc_html', $_ptypes);

    /**
     * Flip to clean the keys (used as <option> values in <select> field on form)
     * Note: Keys *should* be post-type names e.g., "post", "page", "event", etc.
     */
    $_ptypes = array_flip( $_ptypes );
    $_ptypes = array_map('sanitize_key', $_ptypes);

    // Flip back
    $_ptypes = array_flip( $_ptypes );

    asort( $_ptypes );

    return $_ptypes;

}

The pertinent part is right here:

foreach( $post_types as $post_type ){
    if ( post_type_supports( $post_type->name, 'comments' ) ) {
        $query_var = ( ! $post_type->query_var ) ? $post_type->name : $post_type->query_var ;
        $label = $post_type->labels->singular_name;
        $_ptypes[ $query_var ] = $label;
    }
}

What it does is check if the post type supports comments:

post_type_supports( $post_type->name, 'comments' )

The checking for comment support is handled by the core WordPress function, post_type_supports ( string $post_type, string $feature ). This function checks a post type’s support for the given feature. It returns bool (true or false) whether the post type supports the given feature. In this case, we’re passing in “comments” as the feature to check.

If comments, the post type is added to an array of post types that will be used to populate the select drop down. The final array is then passed through the 'acw_allowed_post_types' filter to allow developers to add/remove any post type they’d like.

The feature check that post_type_supports() does is based on the features you can set when calling register_post_type(). Some examples of core features are title, excerpt, comments, and revisions. You can also add your own custom features when registering custom post types.

And there you have it, a really easy way to avoid a potentially confusing experience for your users. Being a plugin developer isn’t just about building cool functionality that extends WordPress, or adding features to a client project. Ok, so it is about that. But it’s about doing it in a responsible manner that makes the experience better for the end user, not just different. It’s about anticipating potential user confusion and addressing it in our build. This little change to the code, adding in the check for comment support, is just one example of how we can accomplish that.

Notes & Resources

The post Checking for Comment Support on Post Types appeared first on darrinb.

]]>
http://darrinb.com/checking-comment-support-post-types/feed/ 0
Filtering the WordPress body_class Function http://darrinb.com/filtering-wordpress-body-class-function/ http://darrinb.com/filtering-wordpress-body-class-function/#comments Mon, 28 Mar 2016 23:14:12 +0000 http://darrinb.com/?p=1502 In this article we'll discuss a short script to add custom classes to the body element of your WordPress page template via the body_class function.

The post Filtering the WordPress body_class Function appeared first on darrinb.

]]>
Update: This post originally ran on May 20, 2010. It has since been updated to accommodate Custom Post Types.

Back in WordPress 2.8, a new template tag was introduced, body_class(). What this template tag does is display dynamic classes for the <body> element of your page. What’s so significant about this function is that this gives us the ability to change the look of essentially every page on a site using CSS only.

How It’s Used

Typically the body_class() tag is placed in the <body> element, which is usually located in the header.php file. It looks like this:

<body <?php body_class(); ?>>

And would return something that looks like this:

<body id="page-about" class="page page-id-71 page-template-default">

See the last two classes, “parent-page and “about? Those are custom classes that this article will discuss in a moment. But first, the template tag itself.

The Codex has a great article explaining in greater detail the various classes this tag creates on the <body> element. We won’t go into too much detail in this article, but you can read the Codex article here. Essentially though, the body_class() tag displays classes in the body element depending what page we’re on, whether the user is logged‐in or not, whether the page is a parent Page, etc. A list of conditionals is available in the Codex article explaining the various classes than can be produced.

Additionally the body_class() tag has the ability to accept additional parameters that you can enter yourself when creating a page template. To do so, you would include this in your template file:

<body <?php body_class('my-class-1 my-class-2'); ?>>

Where “my-class-1” and “my-class-2” were your custom classes. That would then produce something like this:

<body id="page-about" class="page page-id-71 page-template-default my-class-1 my-class-2">

Note: when adding parameters to the body element, you separate each with a space and quote the entire string or place them in an array like so:

<body <?php body_class(array('my-class-1', 'my-class-2')); ?>>

While it’s great to have the ability to manually add classes to the body element using these additional parameters, it still requires the developer to manually add classes. And since we developers should always be looking for ways to streamline our work flow and increase our efficiency, a much easier way would be in the form of a function placed in our functions.php and attached to the body_class filter hook. Read on.

The Code

First, the code in its entirety:

/**
 * Add dynamic classes to the WP body_class() function
 *
 * updated: 01/06/16
 */
function _dbdb_body_classes( $classes ) {
    global $wp_query, $post;

    // if it's the front page of the site
    if ( is_front_page() ) {
        $classes[] = 'front-page';
    }
    
    // url paths
    if ( is_singular() ) {
        // Get the queried post        
        $post_id   = get_queried_object_id();
        $post_type = get_post_type( $post_id );
        $post_type_object = get_post_type_object( $post_type );
        if ( 'post' !== $post_type ) {
            if ( false !== $post_type_object->rewrite ){
                if ( !empty( $post_type_object->rewrite['slug'] ) ){
                    $path = $post_type_object->rewrite['slug'];
                    $path = trim( $path, '/' );
                    if ( !empty( $path ) ) {
                        $matches = explode('/', $path);                        
                        if ( is_array( $matches ) ) {
                            $matches = array_reverse( $matches );
                            $parent_title = sanitize_title( $matches[0] );
                            $classes[] = 'parent-pagename-'.$parent_title;
                            if ( count($matches) > 1 ) {
                                $is_first = true;
                                foreach ( $matches as $ancestor ){
                                    if ( $is_first ) {
                                        $is_first = false;
                                        continue;
                                    }
                                    $ancestor_title = sanitize_title( $ancestor );
                                    $classes[] = 'ancestor-pagename-'.$ancestor_title;
                                }
                            }
                        }
                    }
                }
            }
        }    
    }
        
    // the $post object
    $post_obj = ( property_exists( $wp_query, 'post' ) && isset( $wp_query->post ) ) ? true : false;
    $post_obj_parent = ( $post_obj && property_exists( $wp_query->post, 'post_parent' ) ) ? true : false;    
    
    // if there is no parent ID and it's not a single post page, category page, or 404 page, give it a class of "parent-page"
    if ( $post_obj_parent && $wp_query->post->post_parent < 1  && !is_single() && !is_archive() && !is_404() ) {
        $classes[] = 'parent-page';
    };

    // if the page/post has a parent, it's a child, give it a class of its parent name
    if ( $post_obj_parent && $wp_query->post->post_parent > 0 ) {
        $parent_title = get_the_title($wp_query->post->post_parent);
        $parent_title = sanitize_title($parent_title);
        $classes[] = 'parent-pagename-'.$parent_title;
    };

    // if the page/post has ancestors, get all ancestors' names
    $ancestors = array();
    if ( isset($wp_query->queried_object) && isset($wp_query->queried_object->ancestors) ) {
        $ancestors = $wp_query->queried_object->ancestors;
    }

    if ( is_array($ancestors) && !empty($ancestors) ) {
        foreach($ancestors as $ancestor) {
            $ancestor_title = get_the_title($ancestor);
            $ancestor_title = sanitize_title($ancestor_title);

            $classes[] = 'ancestor-pagename-'.$ancestor_title;
        }
    } else {
        $classes[] = 'top-level-ancestor';
    }


    // get the post categories
    $categories = ( isset($wp_query->queried_object) ) ? get_the_category($wp_query->queried_object_id) : false;
    if ( $categories ) {
        foreach ( $categories as $category ) {
            $classes[] = 'in-category-'.$category->category_nicename;
        }
    }

    // add a class equal to the name of post or page
    if ( isset($wp_query->queried_object) && isset($wp_query->queried_object->post_name) ) {
        $classes[] = 'pagename-'.$wp_query->queried_object->post_name;
    }

	// author
    if ( function_exists( 'is_multi_author' ) && ! is_multi_author() ) {
        $classes[] = 'single-author';
    }

	// single pages
    if ( is_singular() && ! is_home() && ! is_page_template( 'showcase.php' ) && ! is_page_template( 'sidebar-page.php' ) ) {
        $classes[] = 'singular';
    }

    $classes = array_filter($classes);

    return array_unique($classes);
};

add_filter('body_class','_dbdb_body_classes');

The Code Explained

Now let’s break the code down and explain each section. The first thing we need to do is declare the $wp_query as “global” so we can use its values in our function.

Section: Front Page

// if it's the front page of the site
if ( is_front_page() ) {
	$classes[] = 'front-page';
}

Checks whether or not the page is the front page of the site, and if so, adds a class of “front-page”.

Section: URL Paths for Custom Post Types

// url paths
if ( is_singular() ) {
	// Get the queried post        
	$post_id   = get_queried_object_id();
	$post_type = get_post_type( $post_id );
	$post_type_object = get_post_type_object( $post_type );
	if ( 'post' !== $post_type ) {
		if ( false !== $post_type_object->rewrite ){
			if ( !empty( $post_type_object->rewrite['slug'] ) ){
				$path = $post_type_object->rewrite['slug'];
				$path = trim( $path, '/' );
				if ( !empty( $path ) ) {
					$matches = explode('/', $path);                        
					if ( is_array( $matches ) ) {
						$matches = array_reverse( $matches );
						$parent_title = sanitize_title( $matches[0] );
						$classes[] = 'parent-pagename-'.$parent_title;
						if ( count($matches) > 1 ) {
							$is_first = true;
							foreach ( $matches as $ancestor ){
								if ( $is_first ) {
									$is_first = false;
									continue;
								}
								$ancestor_title = sanitize_title( $ancestor );
								$classes[] = 'ancestor-pagename-'.$ancestor_title;
							}
						}
					}
				}
			}
		}
	}    
}

Builds a faux ancester tree based on the rewrite slug of the post type. Basically, if you define a rewrite slug for a custom post type as “assets/properties” this section of the script will create a class called “ancestor-pagename-assets” for all property post types.

Section: Adding Classes Based on Ancestors

// the $post object
$post_obj = ( property_exists( $wp_query, 'post' ) && isset( $wp_query->post ) ) ? true : false;
$post_obj_parent = ( $post_obj && property_exists( $wp_query->post, 'post_parent' ) ) ? true : false;    

// if there is no parent ID and it's not a single post page, category page, or 404 page, give it a class of "parent-page"
if ( $post_obj_parent && $wp_query->post->post_parent < 1  && !is_single() && !is_archive() && !is_404() ) {
	$classes[] = 'parent-page';
};

// if the page/post has a parent, it's a child, give it a class of its parent name
if ( $post_obj_parent && $wp_query->post->post_parent > 0 ) {
	$parent_title = get_the_title($wp_query->post->post_parent);
	$parent_title = sanitize_title($parent_title);
	$classes[] = 'parent-pagename-'.$parent_title;
};

// if the page/post has ancestors, get all ancestors' names
$ancestors = array();
if ( isset($wp_query->queried_object) && isset($wp_query->queried_object->ancestors) ) {
	$ancestors = $wp_query->queried_object->ancestors;
}

if ( is_array($ancestors) && !empty($ancestors) ) {
	foreach($ancestors as $ancestor) {
		$ancestor_title = get_the_title($ancestor);
		$ancestor_title = sanitize_title($ancestor_title);

		$classes[] = 'ancestor-pagename-'.$ancestor_title;
	}
} else {
	$classes[] = 'top-level-ancestor';
}

This checks whether or not the Page has a parent ID of “0” and that it’s not a single Post page, an archive page, and a 404 error page (these all have post_parent ID’s of “0”, but they’re not parents of any other page). If it does—and it’s not one of those types of pages—then it’s a parent page, so we create a class of “parent-page” and add it to the $classes array.

Yes, the current body_class() function already assigns a class of “page-parent” if the page is a parent Page, but in my testing I discovered it didn’t do it for all pages that should be categorized as a parent. For example, using the default body_class() template tag, the Home page of this site returns the following body classes:

<body id="page-home" class="home page page-id-15 page-template page-template-page-templates page-template-page-home page-template-page-templatespage-home-php">

As you can see, even though it’s technically a parent page (because it’s not a child of any other page), it’s not given a class of “page-parent” by the default body_class() tag. That’s where this custom filter function comes in. The classes returned for the Home page by the custom filter are:

<body id="page-home" class="home page page-id-15 page-template page-template-page-templates page-template-page-home page-template-page-templatespage-home-php front-page parent-page top-level-ancestor pagename-home single-author singular">

The second block in the script checks to see if the current page is a child page, and if so, returns the title of its parent as a class. But first, it replaces all spaces in the title with dashes and then converts the entire title to lowercase. (Note: this pulls the title of the page, not its slug.) Finally, it pre-pends the title with “parent-pagename-” for readability.

// if the page/post has a parent, it's a child, give it a class of its parent name
if ( $post_obj_parent && $wp_query->post->post_parent > 0 ) {
	$parent_title = get_the_title($wp_query->post->post_parent);
	$parent_title = sanitize_title($parent_title);
	$classes[] = 'parent-pagename-'.$parent_title;
};

The resulting classes would look like this (taken from the “The Author” page of this site):

<body id="page-the-author" class="page page-id-1207 page-child parent-pageid-71 page-template-default logged-in parent-pagename-about ancestor-pagename-about pagename-the-author single-author singular">

The default body_class() tag returns a class of “parent-pageid-XX”, which is great, but not terribly user-friendly. Developers and designers tend to know the title, rather than the id of their pages, so this function returns that information (“parent-pagename-about”) to be used if needed.

The third block of the script returns the name(s) of any ancestors as classes:

// if the page/post has ancestors, get all ancestors' names
$ancestors = array();
if ( isset($wp_query->queried_object) && isset($wp_query->queried_object->ancestors) ) {
	$ancestors = $wp_query->queried_object->ancestors;
}

if ( is_array($ancestors) && !empty($ancestors) ) {
	foreach($ancestors as $ancestor) {
		$ancestor_title = get_the_title($ancestor);
		$ancestor_title = sanitize_title($ancestor_title);

		$classes[] = 'ancestor-pagename-'.$ancestor_title;
	}
} else {
	$classes[] = 'top-level-ancestor';
}

Section: Taxonomies

// get the post categories
$categories = ( isset($wp_query->queried_object) ) ? get_the_category($wp_query->queried_object_id) : false;
if ( $categories ) {
	foreach ( $categories as $category ) {
		$classes[] = 'in-category-'.$category->category_nicename;
	}
}

This section checks if the post is assigned to any categories and adds any category names as classes. This could be particularly useful with custom taxonomies.

Section: Post Name

The next block of the script returns the name of the page as a class:

// add a class equal to the name of post or page
if ( isset($wp_query->queried_object) && isset($wp_query->queried_object->post_name) ) {
	$classes[] = 'pagename-'.$wp_query->queried_object->post_name;
}

Again using the “The Author” page of this site, we see the following classes returned:

<body id="page-the-author" class="page page-id-1207 page-child parent-pageid-71 page-template-default logged-in parent-pagename-about ancestor-pagename-about pagename-the-author single-author singular">

Section: Single Post/Page

This section will add a class of “.singular” to any single posts or pages using the is_singular() template tag.

// single pages
if ( is_singular() && ! is_home() && ! is_page_template( 'showcase.php' ) && ! is_page_template( 'sidebar-page.php' ) ) {
	$classes[] = 'singular';
}

And finally, the last section of the script returns a unique array of values to avoid duplicate classes from appearing:

return array_unique($classes);

Next we attach the script to the “body_class” filter hook provided by the Core so it’ll execute when called:

add_filter('body_class','_dbdb_body_classes');

Installing The Script

To install, simply copy/paste the code above into your functions.php file and then save the file to your template directory. You can customize it any way you’d like, but be sure to check out the Codex page first to save yourself time.

Notes & Resources

THis script is available as a gist on GitHub: gists/dboutote/body_class.php

In the next article we’ll discuss how to add a custom id to the body element. Classes are great, but ids give fine‐grain control over your CSS. Until then, here are some external resources I’d recommend if you want to learn more about the body_class() tag:

  • See it in the source.
  • Nathan Rice has a great article about the tag located here.
  • The Codex article on the body_class() tag is located here.

The post Filtering the WordPress body_class Function appeared first on darrinb.

]]>
http://darrinb.com/filtering-wordpress-body-class-function/feed/ 11
Adding a Subtitle to the Advanced Comments Widget for WordPress http://darrinb.com/adding-subtitle-advanced-comments-widget/ http://darrinb.com/adding-subtitle-advanced-comments-widget/#respond Sat, 26 Mar 2016 22:43:33 +0000 http://darrinb.com/?p=1416 In the following tutorial we'll explore how to extend the Advanced Comments Widget for WordPress by adding a custom Subtitle field to the widget form.

The post Adding a Subtitle to the Advanced Comments Widget for WordPress appeared first on darrinb.

]]>
Extending the Advanced Comments Widget for WordPress

When the Advanced Comments Widget was initially developed, it was developed for a couple of reasons. Primarily I wanted a better comment list for my site’s sidebar. The default Recent Comments widget is kind of boring, with no avatars or comment excerpts; nothing to draw a site visitor into the conversations happening on the site. Secondly, I wanted to build a customizable widget that provided ways for other developers to adapt the widget for their projects. In this tutorial, I’ll show the steps needed to add a custom form field to the widget form, save that field’s settings, and display the result on comment list displayed on the front end. For this example we’ll be adding a subtitle field to display under the main widget title.

(Click thumbnails to view full size images.)

Getting Started

First, lets take a look at the initial widget:

The initial state of the Advanced Comments Widget
The initial state of the Advanced Comments Widget

In order to extend the widget, you can either roll your own plugin, or add your code to your functions.php file. For the purposes of this tutorial, I wrote a small plugin which is available on GitHub and listed at the bottom of this article.

Adding to the Widget’s Default Values

In order to add our custom field to the widget form we first need to tell the widget it exists. This is done by adding our custom field to the $_defaults array available in the Widget_ACW_Recent_Comments::form() method (link: #). The $_defaults array holds the initial values of the form fields. This builds the initial $instance of the widget, where the $instance is an array of the widget’s settings.

This is what it looks like:

$_defaults = array(
    'title'          => __('Recent Comments'),
    'post_type'      => 'post',
    'exclude_pings'  => 1,
    'number'         => 5,
    'order'          => 'desc',
    'show_thumbs'    => 1,
    'thumb_size'     => 55,
    'show_excerpt'   => 1,
    'excerpt_length' => 50,
    'comment_format' => $_comment_format,
    'list_style'     => $_list_style,
);

$_defaults = apply_filters( 'acw_instance_defaults', $_defaults );

To add your value, tap into the 'acw_instance_defaults' filter and add your own array key/value pair where the key is the $_POST field and the value is the initial value of the field. Like so:

/**
 * Filter the default widget instance
 *
 * @param array $_defaults Current widget values.
 *
 * @return array $_defaults Filtered widget values.
 */
function dbdb_acw_instance_defaults( $_defaults ){

    $_defaults['subtitle'] = __( 'Subtitle' );

    return $_defaults;
}

add_filter( 'acw_instance_defaults', 'dbdb_acw_instance_defaults' );

Adding Our Field to the Widget Form

Now that the widget knows the field exists, we have to add its UI to the form. The Advanced Comments Widget provides action hooks before and after every single form field generated by the plugin, to give developers granular control over where to place their custom fields.

To place a custom field before a default field, use the "acw_form_before_field_{$name}" hook.

To place a custom field after a default field, use the "acw_form_after_field_{$name}" hook.

The full hooks look like:

  • do_action( "acw_form_before_field_{$name}", $instance, $this ),
  • do_action( "acw_form_after_field_{$name}", $instance, $this )

Note: To override a built-in field, you can use the "acw_form_field_{$name}" filter.

In each, the $instance parameter refers to the array of the default widget settings:

Array (
    [title]          => Recent Comments: Posts
    [post_type]      => post
    [exclude_pings]  => 1
    [number]         => 5
    [order]          => desc
    [show_thumbs]    => 1
    [thumb_size]     => 55
    [show_excerpt]   => 1
    [excerpt_length] => 50
    [comment_format] => html5
    [list_style]     => div
    [subtitle]       => Subtitle
)

And the $this parameter refers to current widget object:

Widget_ACW_Recent_Comments Object
(
    [id_base] => acw-recent-comments
    [name] => Advanced Recent Comments
    [widget_options] => Array
        (
            [classname] => widget_acw_recent_comments
            [description] => A comments widget with extended features.
            [customize_selective_refresh] => 1
        )

    [control_options] => Array
        (
            [id_base] => acw-recent-comments
        )

    [number] => 2
    [id] => acw-recent-comments-2
    [updated] =>
    [option_name] => widget_acw-recent-comments
    [alt_option_name] => widget_acw_recent_comments
)

These hooks are provided in the Widget_ACW_Recent_Comments::form() method (link: #).

Note: There are additional hooks & filters available within the form() method.

Since we’re adding a subtitle field, we want it appear below the title field on the form. We do this by tapping in to the 'acw_form_after_field_title' filter. The widget is expecting this to be echoed out to the form, so be sure the function that builds your custom form section echos (not return) its markup like so:


/**
 * Sample form field added via "acw_form_before_field_{$name}" filter
 *
 * @param array $instance Current widget settings.
 * @param object $widget Widget Object.
 */
function dbdb_acw_subtitle_field( $instance, $widget ){
    ?>
    <p>
        <label for="<?php echo $widget->get_field_id( 'subtitle' ); ?>"><?php _e( 'Subtitle:' ); ?></label>
        <input class="widefat" id="<?php echo $widget->get_field_id( 'subtitle' ); ?>" name="<?php echo $widget->get_field_name( 'subtitle' ); ?>" type="text" value="<?php echo esc_attr( $instance['subtitle'] ); ?>" />
    </p>
    <?php
}

add_action( 'acw_form_after_field_title' , 'dbdb_acw_subtitle_field', 0, 2);

Note: If you’re adding a value that doesn’t require user input, you can skip this step.

At this point we should see the new field on the widget form:

The Advanced Comments Widget form after adding the subtitle field.
The Advanced Comments Widget form after adding the subtitle field.

Saving our Field’s Input Value

Now that widget knows the field exists, and we have an input field on the form, we need to save the value and update the widget’s setting when the user changes and saves the widget. We do this by tapping into the 'acw_update_instance' filter. This is available in the Widget_ACW_Recent_Comments::update() method (link: #).

The full filter is: $instance = apply_filters('acw_update_instance', $instance, $new_instance, $old_instance );.

The $instance parameter refers to an array of the widget settings before saving:

Array (
    [title]          => Recent Comments: Posts
    [post_type]      => post
    [exclude_pings]  => 1
    [number]         => 5
    [order]          => desc
    [show_thumbs]    => 1
    [thumb_size]     => 55
    [show_excerpt]   => 1
    [excerpt_length] => 50
    [comment_format] => html5
    [list_style]     => div
    [subtitle]       => Subtitle
)

The $new_instance parameter refers to an array of the submitted settings ($_POST fields):

Array (
    [title]          => Recent Comments
    [subtitle]       => Latest Post Comments
    [post_type]      => post
    [exclude_pings]  => on
    [number]         => 5
    [order]          => desc
    [show_thumbs]    => on
    [thumb_size]     => 36
    [show_excerpt]   => on
    [excerpt_length] => 50
    [list_style]     => div
    [comment_format] => html5
)

In order to save the value from our custom field, we have to filter the $instance and add a reference to our field like so:

/**
 * Hook into the update() method to save custom field.
 *
 * @param array $instance The settings prior to saving.
 * @param array $new_instance New settings for this instance as input by the user via
 *                            Widget_ACW_Recent_Comments::form().
 * @param array $old_instance Old settings for this instance.
 *
 * @return array $instance Updated settings to save.
 */
function dbdb_acw_update_instance( $instance, $new_instance, $old_instance ){

    $instance['subtitle'] = sanitize_text_field( $new_instance['subtitle'] );

    return $instance;
}
add_filter('acw_update_instance', 'dbdb_acw_update_instance', 0, 3);

In our function, we’re tapping into the 'acw_update_instance' filter, adding our custom field to the array, and sanitizing the user’s input before returning the filtered $instance back to the widget. Do not forget to sanitize your inputs.

Once saved, it’s time to display the field.

Displaying the Field Value on the Front End

So far we’ve done the following:

  • Told the widget a custom field exists,
  • Added an input field to the widget form,
  • Saved (and sanitized!) the field’s value

Now we need to display the value on the front end of the site. Here’s the initial comment list:

The initial state of the comments list.
The initial state of the comments list.

What we’re going to do is add the subtitle we saved, below the “Recent Comments” title. The Widget_ACW_Recent_Comments::widget() method (link: #) provides various hooks and filters that allow us to change the display of the list. For this example, we’re going to use the 'acw_widget_title_after' hook.

The full hook is: do_action( 'acw_widget_title_after', $instance );

In this hook, the $instance parameter is the saved settings of the current widget and some identifying information for the current widget:

Array
(
    [title]          => Recent Comments
    [post_type]      => post
    [exclude_pings]  => 1
    [number]         => 5
    [order]          => desc
    [show_thumbs]    => 1
    [thumb_size]     => 36
    [show_excerpt]   => 1
    [excerpt_length] => 50
    [list_style]     => div
    [comment_format] => html5
    [subtitle]       => The Latest Comments From Our Readers
    [id_base]        => acw-recent-comments
    [widget_number]  => 3
    [widget_id]      => acw-recent-comments-3
)

To display our new subtitle we’ll build our function like so:

/**
 * Output Subtitle on the front end
 *
 * @param array $instance Current widget settings.
 */
function dbdb_acw_widget_title_after( $instance ){
    _debug( $instance );

    echo '<h4 class="widget-subtitle">' . __( $instance['subtitle'] ) . '</h4>';

}

add_action( 'acw_widget_title_after',  'dbdb_acw_widget_title_after' );

The resulting comment list should now look like:

The comments list with the new subtitle
The comments list with the new subtitle

Wrap Up

And there you have it, an easy way to extend your site’s comments list!

The Advanced Comments Widget provides numerous action hooks and filters throughout its methods, providing an easy way for developers to adapt the widget to their projects. The possibilities are endless. One example is adding a call-to-action below the comment list using the 'acw_comment_list_after' hook. This is especially helpful if you require your viewers to register an account before leaving comments.

Notes & Resources

The post Adding a Subtitle to the Advanced Comments Widget for WordPress appeared first on darrinb.

]]>
http://darrinb.com/adding-subtitle-advanced-comments-widget/feed/ 0
Advanced Comments Widget: A Developer’s Overview http://darrinb.com/advanced-comments-widget-developers-overview/ http://darrinb.com/advanced-comments-widget-developers-overview/#respond Wed, 23 Mar 2016 04:44:58 +0000 http://darrinb.com/?p=1392 When writing the code for Advanced Comments Widget I had a few goals in mind: Make better comments list for…

The post Advanced Comments Widget: A Developer’s Overview appeared first on darrinb.

]]>
When writing the code for Advanced Comments Widget I had a few goals in mind:

  1. Make better comments list for my sidebar.
  2. Really dig into widgets.
  3. Make it so the widget was easily extensible.

Of course I looked in the repository first, but everything there was either overkill (way too much going on), or didn’t quite fit what I needed. So I decided to roll my own.

Building Better Comment Lists

Let’s face it, the default Recent Comments widget is kind of lame. The lack of an avatar and comment excerpt really don’t entice a viewer on your site to join the conversations happening on your content. What’s the point of showing recent comments if they’re not going to draw people in? The Advanced Comments Widget was built with the intent to provide an easy way to build comment lists for your site’s sidebars.

Digging into Widgets

I’ve built a few widgets in my years as a WordPress dev, but never really dug that deep into them. I wanted to use this opportunity to do just that; learn how to build a solid widget that would provide needed functionality and cool features for mine, and my clients’ sites.

Extensible Widgets

I’ve been a WordPress developer for almost 10 years, and in that time I’ve become very biased to one thing; extensibility. I wish everything in WordPress could be extended/filtered/hooked, so when I build plugins, I try to put in as many filter/action hooks as possible. As you’ll see in the following documentation, the Advanced Comments Widget lives up to this philosophy.

So let’s dig in!

Technical Overview

Normally, when I release a plugin, I break down its various classes/methods into micro-tutorials to explain how it was built, and how it could be replicated in another plugin. If you’d rather skip that and go straight to extending the Advanced Comments Widget, click here: Advanced Comments Widget: Extending the Widget. If you want to learn stuff, read on!

This plugin can be broken down into three classes, each with their distinct responsibilities:

  • ACW_Recent_Comments
  • ACW_Recent_Comments_Utilities
  • Widget_ACW_Recent_Comments

The ACW_Recent_Comments Class

This class is the main administrator of the plugin. It handles registering and loading the widget and the scripts and styles used in the site’s dashboard. I won’t delve too deep into its methods since it doesn’t handle any actual widget functionality. If you’d like to see it in all its glory, you can check it out on GitHub: class ACW_Recent_Comments

The post Advanced Comments Widget: A Developer’s Overview appeared first on darrinb.

]]>
http://darrinb.com/advanced-comments-widget-developers-overview/feed/ 0
Adding a Custom Icon to Your WordPress Plugin http://darrinb.com/adding-custom-icon-wordpress-plugin/ http://darrinb.com/adding-custom-icon-wordpress-plugin/#respond Tue, 22 Mar 2016 21:21:26 +0000 http://darrinb.com/?p=1363 Help your plugin stand out from the crowd! The following is a quick tutorial on adding a custom icon for your WordPress plugin.

The post Adding a Custom Icon to Your WordPress Plugin appeared first on darrinb.

]]>
While working on my recent plugin, Advanced Comments Widget, I decided I wanted to add a cool icon that would show up in search results in the plugin repository. After some research, I couldn’t find information on how to do it though. The Developer FAQ page has info for adding a banner for your plugin page, but nothing about adding an icon. (At least, nothing I could find.)

After some digging, I figured out the dead-simple way to accomplish this. Basically, you follow the same guidelines for adding a banner to your plugin page.

From the Developer FAQ:

Start by creating an assets/ directory in the root of your SVN checkout (if one doesn’t already exist). This will be on the same level as tags/ and trunk/, for example.

Inside that assets/ directory, you can make a file named banner-772×250.png or banner-772×250.jpg. The image must be exactly 772 pixels wide and 250 pixels tall. No GIFs.

Instead of creating a file named banner-772x250.png or banner-772x250.jpg, create a file named icon-128x128.png or icon-128x128.jpg. The dimensions for your plugin icon must be 128 pixels wide by 128 pixels tall.

If you want to support high-DPI (aka “retina”) displays, you can make a file named icon-256x256.png or icon-256x256.jpg. As with the standard size plugin icon, the dimensions for your retina-ready must be exact. In this case it’s 256 pixels wide by 256 pixels tall. If present, this image will be served when the website detects a browser on a high-DPI display.

After checking in the new icon(s), it will appear the next time the plugin is refreshed in the directory. During my testing, it only took a few minutes.

Why add an icon?

Let’s take a look at an example.

Here’s a “before” picture of the Advanced Comments Widget appearing in search results:

plugin without icon

And here’s an “after”:

plugin with icon

You’ll notice in the before shot, the plugin doesn’t really stand out. But in the after, it pops out. Even though the directory auto-creates cool graphical icons if your plugin doesn’t have an icon file, they’re kind of nondescript and blend in with the background. Adding your own custom icon to your plugin allows you to A: brand your plugin more in-line with your brand, and B: make your plugin stand out a little more in search results.

And there you have it; a really easy way to add an icon for your plugin and have it stand out in search results!

The post Adding a Custom Icon to Your WordPress Plugin appeared first on darrinb.

]]>
http://darrinb.com/adding-custom-icon-wordpress-plugin/feed/ 0
Advanced Comments Widget http://darrinb.com/advanced-comments-widget/ http://darrinb.com/advanced-comments-widget/#respond Fri, 18 Mar 2016 05:23:18 +0000 http://darrinb.com/?p=1314 Make your recent comments stand out with the new Advanced Comments Widget. This recent comments widget provides advanced features for customizing your recent comments lists.

The post Advanced Comments Widget appeared first on darrinb.

]]>
Let’s face it, the default Recent Comments widget is kind of lame. There’s no user avatar, no comment blurb; nothing to draw you into the conversations happening on the site. What’s the point of showing recent comments on your site if they don’t prompt your viewers to leave their own?

That’s where the Advanced Comments Widget comes in.

Features/Options

This widget provides a range of features; allowing you to customize your recent comments list to match your site’s layout and theme.

Option: Widget Title

advanced comments widget title option
Similar to the default Recent Comments widget, the Advanced Comments Widget allows you to set a custom title for your comment list. The default setting is “Recent Comments”, but you can change it to whatever you’d like, or leave it blank.

Option: Post Types

advanced comments widget post-type option
Want to build a list of comments based on a specific post type? With the Advanced Comments Widget, it’s as easy as selecting an option from a dropdown. This widget auto-detects all the registered post types on your site–that have commenting enabled–and adds them to this option in the widget form. This option defaults to “post”.

Option: Pingbacks and Trackbacks

advanced comments widget pingback option
Recent comment lists are a great way to add user-generated content to your site. Listing trackbacks and pingbacks don’t really add value to your sidebar. The Advanced Comments Widget gives you the option to either include or exclude pingbacks and trackbacks from your comment list. The default setting is “exclude”.

Option: Number of Comments

advanced comments widget comment-number option
The Advanced Comments Widget lets you easily set the number of comments you want to display.

Option: Comment Order

advanced comments widget comment-order option
Generally, comment lists in sidebars are set to display the newest comments first. There may be times when you want older comments to appear first. The Advanced Comments Widget gives you the option of ordering by newer or older comments. The default setting is to display newer comments first.

Option: Comment Avatars

advanced comments widget avatar option
Add some characters to your comment list! The Advanced Comments Widget gives you the option to include the comment author’s avatar when displaying his/her comment. What’s more, you can also set the size of the displayed avatar to fit with your site’s overall look and style. And even better, you can preview your size before saving. No more guessing and adjusting!

Option: Comment Excerpts

advanced comments widget comment-excerpt option
In addition to avatars, the Advanced Comments Widget also has the option to include comment excerpts in your comment lists. You can also easily set the excerpt length to fit within your site’s design.

Option: Comment Format

advanced comments widget comment-format-list option

advanced comments widget comment-format-comment option

Gone are the days of being forced into a set html structure for your comments! The Advanced Comments Widget lets you select the list structure for your comments. Want to display them as an ordered list? Sure thing! An unordered list? You bet! Just want to wrap them in div tags? Not a problem. Don’t know which one to choose? Not to worry! The Advanced Comments Widget auto-detects whether or not your site supports html5 comments and set the defaults accordingly.

The Resulting List

With a little bit of styling (to keep it in-style with your site) the resulting list can look similar to this:

advanced-comments-widget-comment-list

Installation

As of this writing, the plugin is awaiting review by the plugin team at the WordPress.org repository, but in the meantime, you can download and install off of GitHub. Just follow the instructions below.

Update : The plugin has been approved by the Review Team and is now available on the WordPress plugin repository: https://wordpress.org/plugins/advanced-comments-widget/

From the WordPress.org plugin repository:

  1. Download and install using the built in WordPress plugin installer.
  2. Activate in the “Plugins” area of your admin by clicking the “Activate” link.
  3. No further setup or configuration is necessary; just head over to your Widgets area to add to your sidebar.

From GitHub:

  1. Download the latest stable version.
  2. Extract the zip folder to your plugins directory.
  3. Activate in the “Plugins” area of your admin by clicking the “Activate” link.
  4. No further setup or configuration is necessary; just head over to your Widgets area to add to your sidebar.

Usage

Using it out of the box is really straight-forward. The Advanced Comments Widget functions like any other widget for WordPress. You can either configure one it through the Widgets screen in your WordPress Dashboard (Appearance > Widgets) or through your the Customizer (Appearance > Customizer).

Note: Unlike the default Recent Comments widget that comes pre-installed with WordPress, the Advanced Comments Widget assigns unique IDs to each list created. So feel free to create as many comment lists with as many configurations as you’d like!

A Note for Developers

This widget was built not only with end-users in mind, but also plugin developers. Almost every aspect of this widget is extensible through filters and action hooks. You can even add your own form fields to the widget form!

  • Need to remove a field from the widget form? Not a problem! Every field is passed through its own filter for easy customization.
  • Need to modify the output of the widget? Easy! The output is passed through numerous filters, allowing you to customize the comment list to meet your project’s requirements.

Check back soon for a full list of developer features as well as some sample functions! The developer docs are now available here: ACW Developer Docs

The post Advanced Comments Widget appeared first on darrinb.

]]>
http://darrinb.com/advanced-comments-widget/feed/ 0
Bootstrap Comments for WordPress http://darrinb.com/wp-bootstrap-comments/ http://darrinb.com/wp-bootstrap-comments/#respond Sun, 17 Jan 2016 16:44:04 +0000 http://darrinb.com/?p=1240 WP Bootstrap Comments for WordPress provides a comment walker class for building Bootstrap-compatible nested comment threads for WordPress posts. It merges the required markup and classes needed by Bootstrap with the classes and markup typically used by WordPress in the native comment walker class.

The post Bootstrap Comments for WordPress appeared first on darrinb.

]]>
WP Bootstrap Comments for WordPress provides a comment walker class for building Bootstrap-compatible nested comment threads for WordPress posts. It merges the required markup and classes needed by Bootstrap with the classes and markup typically used by WordPress in the native comment walker class.

When I decided to redesign this site earlier this year, I decided to go with Bootstrap as my front end framework. I find it easy to use, well-documented, and flexible enough for my needs. Being a “from scratch” kind of guy, I always build my themes from from the ground up–utilizing various frameworks and libraries–but always writing the markup myself. Given that I decided to use Bootstrap to handle the site’s responsive requirements, I set about integrating Bootstrap classes into native WordPress markup.

When it came time to build out the comments section for my posts, I admit I was stumped at first. Bootstrap has a Media component that handles styling for building various media lists (like comments), but it requires different markup than what WP does out-of-the-box. While Bootstrap structurally nests comments (where one comment is a child of another), WordPress only visually nests comments. While the Walker_Comment class may build individual comments, it doesn’t build a list of nested comments.

This is the markup the Walker_Comment class creates:

<div id="comment-19" class="comment odd alt thread-odd thread-alt depth-1 parent">
    <article id="div-comment-19" class="comment-body">
        <footer class="comment-meta">
            <div class="comment-author vcard">
                [avatar] 
                [author name]                
            </div>    
            <div class="comment-metadata">
                [comment timestamp]
                [edit link]                
            </div>    
        </footer>    
        <div class="comment-content">
            [comment content]
        </div>    
        <div class="reply">
           [reply link]
        </div>            
    </article>    
    <div id="comment-219" class="comment byuser comment-author-darrinb bypostauthor even depth-2">
        <article id="div-comment-219" class="comment-body">
            <footer class="comment-meta">
                <div class="comment-author vcard">
                    [avatar]
                    [author name]                
                </div>    
                <div class="comment-metadata">
                    [comment timestamp]
                    [edit link]                
                </div>    
            </footer>    
            <div class="comment-content">
                [comment content]
            </div>    
            <div class="reply">
                [reply link]
            </div>    
        </article>    
    </div>    
</div>

Note that each comment article tag is wrapped in a div tag and the child div tags are within the parent div tag, they’re not within the parent article tag. Bootstrap needs the child comments to be nested within the parent comment itself, not the comment’s outer wrapper tag. E.g., within the parent article tag, not the parent div tag.

This is the markup Bootstrap needs*:

<div class="media"> <!-- parent comment wrapper -->
    <div class="media-left">
        [avatar]
    </div>
    <div class="media-body"> <!-- parent comment content -->
        <h4 class="media-heading">[author]</h4>
        [comment content]
        <div class="media"> <!-- child comment wrapper -->
            <div class="media-left">
                [avatar]
            </div>
            <div class="media-body"> <!-- child comment content -->
                <h4 class="media-heading">[author]</h4>
                [comment content]
            </div>
        </div>
    </div>
</div>

Note how the child comments sits within the parent media-body tag. I needed to replicate this behavior in a WordPress comment list so I could utilize Bootstrap’s built-in classes. This proved more challenging than I originally thought given that the default walker outputs each comment in its entirety, and I needed a way to essentially inject a child comment within a parent comment. A quick Google search turned up walkers that build out Bootstrap-compatible comments in various forms, but none (that I could find) accounted for nested comments, so I decided to roll my own.

Enter the WP Bootstrap Comments plugin.

Technical Overview

(Click here to skip this section and go straight to the install steps.)

The WP_Bootstrap_Comments_Walker class was modeled closely off the core Walker_Comment class. It bridges native WordPress markup with Bootstrap styles allowing the use of the Bootstrap v3 framework.

WP_Bootstrap_Comments_Walker::start_el()

Method: Starts the comment output. Will check if the comment has children or is a stand-alone comment.

This is the method that starts building the comment. It determines what type of comment is being requested (pingback, trackback, html5, or the default xhtml) and calls the corresponding builder method. If it determines the comment being built has children, it will call the parent method: start_parent_html5_comment().

/**
 * Start the element output.
 *
 * This opens the comment.  Will check if the comment has children or is a stand-alone comment.
 *
 * @access public
 * @since 0.1.0
 *
 * @see Walker::start_el()
 * @see wp_list_comments()
 *
 * @global int        $comment_depth
 * @global WP_Comment $comment
 *
 * @param string $output  Passed by reference. Used to append additional content.
 * @param object $comment Comment data object.
 * @param int    $depth   Depth of comment in reference to parents.
 * @param array  $args    An array of arguments.
 */
public function start_el( &$output, $comment, $depth = 0, $args = array(), $id = 0 )
{
    $depth++;
    $GLOBALS['comment_depth'] = $depth;
    $GLOBALS['comment'] = $comment;
    if ( !empty( $args['callback'] ) ) {
        ob_start();
        call_user_func( $args['callback'], $comment, $args, $depth );
        $output .= ob_get_clean();
        return;
    }
    if ( ( 'pingback' == $comment->comment_type || 'trackback' == $comment->comment_type ) && $args['short_ping'] ) {
        ob_start();
        $this->ping( $comment, $depth, $args );
        $output .= ob_get_clean();
    } elseif ( 'html5' === $args['format'] ) {
        ob_start();
        if ( !empty( $args['has_children'] ) ) {
            $this->start_parent_html5_comment( $comment, $depth, $args );
        } else {
            $this->html5_comment( $comment, $depth, $args );
        }
        $output .= ob_get_clean();
    } else {
        ob_start();
        $this->comment( $comment, $depth, $args );
        $output .= ob_get_clean();
    }
}

WP_Bootstrap_Comments_Walker::end_el()

Method: Ends the comment output, if needed. Will check if the comment has children or is a stand-alone comment.

Similar to start_el(), this method determines if the comment has children or not. If it does, it calls the end_parent_html5_comment() method. If it doesn’t have children, it will simply output the required closing tag.

/**
 * Ends the element output, if needed.
 *
 * This ends the comment.  Will check if the comment has children or is a stand-alone comment.
 *
 * @access public
 * @since 0.1.0
 *
 * @see Walker::end_el()
 * @see wp_list_comments()
 *
 * @param string     $output  Passed by reference. Used to append additional content.
 * @param WP_Comment $comment The comment object. Default current comment.
 * @param int        $depth   Depth of comment.
 * @param array      $args    An array of arguments.
 */
public function end_el( &$output, $comment, $depth = 0, $args = array() )
{
    if ( !empty( $args['end-callback'] ) ) {
        ob_start();
        call_user_func( $args['end-callback'], $comment, $args, $depth );
        $output .= ob_get_clean();
        return;
    }
    if ( !empty( $args['has_children'] ) && 'html5' === $args['format']) {
        ob_start();
        $this->end_parent_html5_comment( $comment, $depth, $args );
        $output .= ob_get_clean();
    } else {
        if ( 'div' == $args['style'] ) {
            $output .= "</div><!-- #comment-## -->\n";
        } else {
            $output .= "</li><!-- #comment-## -->\n";
        }
    }
}

WP_Bootstrap_Comments_Walker::start_parent_html5_comment()

Method: Outputs the beginning of an html5 parent comment.

Since Bootstrap requires child comments to sit within their parent comment, this method writes the opening of an html5 comment and excludes the closing tags so children comments can be nested inside. It does this by calling the html5_comment() method with the $is_parent flag set to true.

/**
 * Output the beginning of a parent comment in the HTML5 format.
 *
 * Bootstrap media element requires child comments to be nested within the parent media-body.
 * The original comment walker writes the entire comment at once, this method writes the opening
 * of a parent comment so children comments can be nested within.
 *
 * @access protected
 * @since 0.1.0
 *
 * @see http://getbootstrap.com/components/#media
 * @see wp_list_comments()
 *
 * @param object $comment Comment to display.
 * @param int    $depth   Depth of comment.
 * @param array  $args    An array of arguments.
 */
protected function start_parent_html5_comment( $comment, $depth, $args )
{
    $this->html5_comment( $comment, $depth, $args, $is_parent = true );
}

WP_Bootstrap_Comments_Walker::html5_comment()

Method: Builds the comment markup.

Here we get into the meat of the plugin. This method outputs the majority of the markup needed to display an html5 comment.

/**
 * Output a comment in the HTML5 format.
 *
 * @access protected
 * @since 0.1.0
 *
 * @see wp_list_comments()
 *
 * @param object  $comment   Comment to display.
 * @param int     $depth     Depth of comment.
 * @param array   $args      An array of arguments.
 * @param boolean $is_parent Flag indicating whether or not this is a parent comment
 */
protected function html5_comment( $comment, $depth, $args, $is_parent = false )
{
    $tag = ( 'div' === $args['style'] ) ? 'div' : 'li';
    $type = get_comment_type();
    $comment_classes = array();
    $comment_classes[] = 'media';
    // if it's a parent
    if ( $this->has_children ) {
        $comment_classes[] = 'parent';
        $comment_classes[] = 'has-children';
    }
    // if it's a child
    if ( $comment->comment_parent > 0 ) {
        $comment_classes[] = 'child';
        $comment_classes[] = 'has-parent';
        $comment_classes[] = 'parent-' . $comment->comment_parent;
    }
    $comment_classes = apply_filters( 'wp_bootstrap_comment_class', $comment_classes, $comment, $depth, $args );
    $class_str = implode(' ', $comment_classes);
?>
    <<?php echo $tag; ?> id="comment-<?php comment_ID(); ?>" <?php comment_class( $class_str, $comment ); ?>>

        <article id="div-comment-<?php comment_ID(); ?>" class="comment-body">

            <?php if ( 0 != $args['avatar_size'] && 'pingback' !== $type && 'trackback' !== $type ) { ?>
                <div class="media-left">
                    <?php echo $this->get_comment_author_avatar( $comment, $args ); ?>
                </div>
            <?php }; ?>

            <div class="media-body">

                <footer class="comment-meta">
                    <div class="comment-author vcard">
                        <?php printf( __( '%s <span class="says sr-only">says:</span>' ), sprintf( '<b class="media-heading fn">%s</b>', get_comment_author_link( $comment ) ) ); ?>
                    </div><!-- /.comment-author -->

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

                    <?php if ( '0' == $comment->comment_approved ) : ?>
                        <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(); ?>
                </div><!-- /.comment-content -->

                <?php $this->comment_reply_link( $comment, $depth, $args, $add_below = 'reply-comment' ); ?>

                <?php if ( $is_parent ) { ?>
                    <div class="child-comments">
                <?php } else { ?>
                        </div><!-- /.media-body -->
                    </article><!-- /.comment-body -->
                <?php } ?>

<?php
}

It begins by determining which wrapper element to generate; either a div or an li tag.

<<?php echo $tag; ?> id="comment-<?php comment_ID(); ?>" <?php comment_class( $class_str, $comment ); ?>>

Following this, it determines which classes to apply to this wrapper element by checking the $this->has_children $comment->comment_parent properties. These classes are then filterable by applying the wp_bootstrap_comment_class filter to the $comment_classes array prior to generating the classes string.

$comment_classes = apply_filters( 'wp_bootstrap_comment_class', $comment_classes, $comment, $depth, $args );

Digging further, the method checks if the avatar_size argument was passed in, and if it has (and this comment is not a ping/trackback), builds out the avatar section.

<?php if ( 0 != $args['avatar_size'] && 'pingback' !== $type && 'trackback' !== $type ) { ?>
    <div class="media-left">
        <?php echo $this->get_comment_author_avatar( $comment, $args ); ?>
    </div>
<?php }; ?>

The next section builds out the content section of the comment. This is where the author name, time stamp, and actual comment are displayed.

[

]
<div class="media-body">

    <footer class="comment-meta">
        <div class="comment-author vcard">
            <?php printf( __( '%s <span class="says sr-only">says:</span>' ), sprintf( '<b class="media-heading fn">%s</b>', get_comment_author_link( $comment ) ) ); ?>
        </div><!-- /.comment-author -->

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

        <?php if ( '0' == $comment->comment_approved ) : ?>
            <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(); ?>
    </div><!-- /.comment-content -->

    <?php $this->comment_reply_link( $comment, $depth, $args, $add_below = 'reply-comment' ); ?>

It’s all pretty standard up to this point; mostly just a re-write of the original Walker_Comment class and adding in Bootstrap classes where needed. The section after the reply link ($this->comment_reply_link()) is where the Bootstrap nesting begins. Here we check if the comment has children by checking if the $is_parent flag is set to true. Remember, this was set by the start_parent_html5_comment() method. If it is, we open the child comments div. If not, we close out the comment.

<?php if ( $is_parent ) { ?>
    <div class="child-comments">
<?php } else { ?>
        </div><!-- /.media-body -->
    </article><!-- /.comment-body -->
<?php } ?>

WP_Bootstrap_Comments_Walker::end_parent_html5_comment()

Method: Outputs the end of an html5 parent comment.

Here we close out the parent html5 comment. This outputs the closing child comments section, the parent media body section, the parent article tag, and the parent wrapper element.

This method is called by WP_Bootstrap_Comments_Walker::end_el().

/**
 * Output the end of a parent comment in the HTML5 format.
 *
 * Bootstrap media element requires child comments to be nested within the parent media-body.
 * The original comment walker writes the entire comment at once, this method writes the end
 * of a parent comment so child comments can be nested within.
 *
 * @see http://getbootstrap.com/components/#media
 *
 * @access protected
 * @since 0.1.0
 *
 * @see wp_list_comments()
 *
 * @param object $comment Comment to display.
 * @param int    $depth   Depth of comment.
 * @param array  $args    An array of arguments.
 */
protected function end_parent_html5_comment( $comment, $depth, $args )
{
    $tag = ( 'div' === $args['style'] ) ? 'div' : 'li';
?>
                </div><!-- /.child-comments -->
            </div><!-- /.media-body -->
        </article><!-- /.comment-body -->
    </<?php echo $tag; ?>><!-- /.parent -->

<?php
}

WP_Bootstrap_Comments_Walker::ping()

Method: Outputs a pingback comment.

Pingbacks and trackbacks are not forgotten! This method builds out a pingback comment with Bootstrap classes applied.

Note: This will only be used if the short_ping argument is passed to the wp_list_comments() function in your comments.php template. If the short_ping argument is not passed, a full comment will be built using either the WP_Bootstrap_Comments_Walker::html5_comment() method or the Walker_Comment::comment() method.

/**
 * Output a pingback comment
 *
 * @access protected
 * @since 0.1.0
 *
 * @see wp_list_comments()
 *
 * @param WP_Comment $comment The comment object.
 * @param int        $depth   Depth of comment.
 * @param array      $args    An array of arguments.
 */
protected function ping( $comment, $depth, $args ) {
    $tag = ( 'div' == $args['style'] ) ? 'div' : 'li';
    $comment_classes = array();
    $comment_classes[] = 'media';
    $comment_classes = apply_filters( 'wp_bootstrap_comment_class', $comment_classes, $comment, $depth, $args );
    $class_str = implode(' ', $comment_classes);
?>
    <<?php echo $tag; ?> id="comment-<?php comment_ID(); ?>" <?php comment_class( $class_str, $comment ); ?>>
        <div class="comment-body">
            <div class="media-body">
                <?php _e( 'Pingback:' ); ?> <?php comment_author_link( $comment ); ?> <?php edit_comment_link( __( 'Edit' ), '<span class="edit-link">', '</span>' ); ?>
            </div><!-- /.media-body -->
        </div><!-- /.comment-body -->
<?php
}

WP_Bootstrap_Comments_Walker::get_comment_author_avatar()

Method: Generate avatar markup

This method builds the markup for displaying the avatar. If an author url can be retrieved, the avatar is wrapped in a link to the comment author’s url. If no url is retrieved only the avatar is displayed.

/**
 * Generate avatar markup
 *
 * @access protected
 * @since 0.1.0
 *
 * @param object $comment Comment to display.
 * @param array  $args    An array of arguments.
 */
protected function get_comment_author_avatar( $comment, $args )
{
    $avatar_string = get_avatar( $comment, $args['avatar_size'] );
    $comment_author_url = get_comment_author_url( $comment );
    if ( '' !== $comment_author_url ) {
        $avatar_string = sprintf(
            '<a href="%1$s" class="author-link url" rel="external nofollow">%2$s</a>',
            esc_url($comment_author_url),
            $avatar_string
        );
    };
    return $avatar_string;
}

Method: Generate markup for the comment reply link

This method generates the markup to display the comment reply link.

Note: this differs from the standard comment reply link in that the link will append the comment form after the actual reply link, not the comment itself. The default behavior of placing the form after the comment wrapper div results in a poor user experience on comments that have a lot of replies; it pushes the form too far down to see the actual comment you’re replying to. This method places the form directly below the reply link, where you can still see the comment you’re replying to.

/**
 * Displays the HTML content for reply to comment link.
 *
 * @access protected
 * @since 0.1.0
 *
 * @param object $comment   Comment being replied to. Default current comment.
 * @param int    $depth     Depth of comment.
 * @param array  $args      An array of arguments for the Walker Object
 * @param string $add_below The id of the element where the comment form will be placed
 */
protected function comment_reply_link( $comment, $depth, $args, $add_below = 'div-comment' )
{
    $type = get_comment_type();
    if ( 'pingback' === $type || 'trackback' === $type ) {
        return;
    }
    comment_reply_link( array_merge( $args, array(
        'add_below' => $add_below,
        'depth'     => $depth,
        'max_depth' => $args['max_depth'],
        'before'    => '<div id="reply-comment-'.$comment->comment_ID.'" class="reply">',
        'after'     => '</div>'
    ) ) );
}

The Resulting Markup

Once activated the resulting markup will look similar to this:

<div id="comment-01" class="comment odd alt thread-odd thread-alt depth-1 media parent has-children">

    <article id="div-comment-01" class="comment-body">

        <div class="media-left">
            <a href="http://author-url.com" class="author-link url" rel="external nofollow">
                <img alt='' src='http://gravatar-url.com' srcset='http://gravatar-url.com?s=72&amp;d=mm&amp;r=g 2x' class='avatar media-object img-circle avatar-36 photo' height='36' width='36' />
            </a>
        </div>

        <div class="media-body">

            <footer class="comment-meta">
                <div class="comment-author vcard">
                    <b class="media-heading fn"><a href='http://author-url.com' rel='external nofollow' class='url'>Author</a></b> <span class="says sr-only">says:</span>
                </div>
                <div class="comment-metadata">
                    <a href="http://post-url.com/#comment-01"> <time datetime="0000-00-00T00:00:00+00:00"> Month 01, YEAR at H:mm pm </time> </a>
                </div>
            </footer>

            <div class="comment-content">
                <p>Comment text.</p>
            </div>

            <div id="reply-comment-01" class="reply">
                <a rel='nofollow' class='comment-reply-link' href='http://post-url.com/?replytocom=19#respond' onclick='return addComment.moveForm( "reply-comment-01", "19", "respond", "543" )' aria-label='Reply to Author'>Reply</a>
            </div>

            <div class="child-comments">

                <div id="comment-02" class="comment byuser comment-author-postauthor bypostauthor even depth-2 media child has-parent parent-01">
                    <article id="div-comment-02" class="comment-body">
                        <div class="media-left">
                            <img alt='' src='http://gravatar-url.com' srcset='http://gravatar-url.com?s=72&amp;d=mm&amp;r=g 2x' class='avatar media-object img-circle avatar-36 photo' height='36' width='36' />
                        </div>
                        <div class="media-body">
                            <footer class="comment-meta">
                                <div class="comment-author vcard">
                                    <b class="media-heading fn">Author</b> <span class="says sr-only">says:</span>
                                </div>
                                <div class="comment-metadata">
                                    <a href="http://post-url.com/#comment-02"> <time datetime="0000-00-00T00:00:00+00:00"> Month 01, YEAR at H:mm pm </time> </a>
                                </div>
                            </footer>
                            <div class="comment-content">
                                <p>Comment text.</p>
                            </div>
                        </div>
                    </article>
                </div>

                <div id="comment-03" class="comment odd alt depth-2 media child has-parent parent-01">
                    <article id="div-comment-03" class="comment-body">
                        <div class="media-left">
                            <a href="http://author-url.com" class="author-link url" rel="external nofollow">
                                <img alt='' src='http://gravatar-url.com' srcset='http://gravatar-url.com?s=72&amp;d=mm&amp;r=g 2x' class='avatar media-object img-circle avatar-36 photo' height='36' width='36' />
                            </a>
                        </div>
                        <div class="media-body">
                            <footer class="comment-meta">
                                <div class="comment-author vcard">
                                    <b class="media-heading fn"><a href='http://author-url.com' rel='external nofollow' class='url'>Author</a></b> <span class="says sr-only">says:</span>
                                </div>
                                <div class="comment-metadata">
                                    <a href="http://post-url.com/#comment-03"> <time datetime="0000-00-00T00:00:00+00:00"> Month 01, YEAR at H:mm pm </time> </a>
                                </div>
                            </footer>
                            <div class="comment-content">
                                <p>Comment text.</p>
                            </div>
                        </div>
                    </article>
                </div>

            </div><!-- /.child-comments -->

        </div><!-- /.media-body -->

    </article><!-- /.comment-body -->

</div><!-- /.parent -->

As you can see, the resulting markup follows the Bootstrap markup convention of giving each comment wrapper a class of media, a media-left div for avatars, and a media-body div for the comment content. It also adds the media-heading class on the b tag within the comment-author div. And all child comments are nested within the media-body div of their respective parent comments. This markup allows you to use native Bootstrap v3 styling while still maintaining (mostly) native WordPress comment structure.

Installation

The plugin is awaiting review by the plugin team at the WordPress.org repo, but in the meantime, you can download and install off of GitHub. Just follow the instructions below.

Update January 21, 2016: The plugin has been approved by the Review Team and is now available on the WordPress plugin repository: https://wordpress.org/plugins/wp-bootstrap-comments/

From the WordPress.org plugin repository:

  1. Download and install using the built in WordPress plugin installer.
  2. Activate in the “Plugins” area of your admin by clicking the “Activate” link.
  3. No further setup or configuration is necessary; just head over to your Widgets area to add to your sidebar.

From GitHub:

  1. Download the latest stable version.
  2. Extract the zip folder to your plugins directory.
  3. Activate in the “Plugins” area of your admin by clicking the “Activate” link.
  4. No further setup or configuration is necessary.

Usage

Using it out of the box is really straight-forward. Just add a call to the class in the walker argument of wp_list_comments() in your comments.php template. Like so:

wp_list_comments( array(
    'style'       => 'div',
    'short_ping'  => true,
    'avatar_size' => 42,
    'walker' => new WP_Bootstrap_Comments_Walker(),
) );

If you’re using the ol or ul style arguments you can use Boostrap’s native media styles by adding the media-list class to your list element like so:

<ul class="media-list">
    <?php
        wp_list_comments( array(
            'style'       => 'ul',
            'short_ping'  => true,
            'avatar_size' => 42,
            'walker' => new WP_Bootstrap_Comments_Walker(),
        ) );
    ?>
</ul><!-- /.media-list -->

Notes & Resources

You can check out the full project on GitHub here: WP Bootstrap Comments

The following are various functions, methods, documents mentioned throughout this post. They’re compiled here for easy reference.

  • * Bootstrap does not specifically need an h4 tag here, just the media-heading class.

The post Bootstrap Comments for WordPress appeared first on darrinb.

]]>
http://darrinb.com/wp-bootstrap-comments/feed/ 0