From iThemes Codex
Revision as of 19:49, 14 July 2011 by Ronalfy (talk | contribs) (The Loop Standard)
Jump to: navigation, search

Release date: TBA

Sample Layouts and Queries

Please see below for a ZIP file of some sample layouts and queries that can be imported.

LoopBuddy Export File


The LoopBuddy shortcode takes two attributes: a Query ID and a Layout ID.

Simply insert the shortcode into a post or page:

[loopbuddy query_id='0' layout_id='0']

The Loop Standard

The Loop Standard divides a loop into two main concepts: a loop and one or more entries.

Both a loop and an entry have three sections: a header, a content section, and a footer. The header contains title information, any meta information, and any necessary navigation links. The content section contains the content relevant to that loop or entry. The footer section is a place to hold additional or duplicate meta information and navigation links.

The Loop Explained

The content of a loop is a bit more complex than the content of an entry as a loop's content contains the entries. To better visualize this, here is the basic structure described so far:

  • Loop
    • Header
      • title
      • navigation
      • meta
    • Content
      • Entry
        • Header
          • title
          • navigation
          • meta
        • Content
        • Footer
          • navigation
          • meta
      • Additional entries...
      • Footer
        • navigation
        • meta

The idea is that each section is broken out in a repeatable pattern. This makes styling easier as any content that follows this form can be styled without having to first read through the code in order to understand the structure.

You may notice that there are titles, navigation, and meta for both the entries and the loop. This is because some titles, navigation, and meta are relevant to the loop (the title archive, navigating between pages of posts, or information about an author in an author archive) while other titles, navigation, and meta are relevant to the entry (the blog post's title, navigating through a page split into multiple pages, or a blog post's category information). The rule of thumb is that if the information is specific to an individual post's, page's, etc content, it is an entry-level structure; otherwise, it is a loop-level structure.

Each of these sections have a specific class in the Loop Standard. Here is the structure again with the classes replacing the names:

  • loop
    • loop-header
      • loop-title
      • loop-utility
      • loop-meta
    • loop-content
      • hentry
        • entry-header
          • entry-title
          • entry-utility
          • entry-meta
        • entry-content
        • entry-footer
          • entry-utility
          • entry-meta
      • hentry...
    • loop-footer
      • loop-utility
      • loop-meta

Notice the "hentry" class. This looks odd but is actually generated by WordPress internally. It is produced by the post_class() function that is in 2010 and 2011 theme template files. So when you see "hentry", know that this is simply the div that looks like :

<div <?php post_class(); ?>></div>

Here is the standard loop in practice:

  • loop
    • loop-header
      • loop-title (page-title)
    • loop-content
      • hentry
        • entry-header (title)
          • entry-title (post-title)
          • entry-meta (post-meta)
          • entry-meta date (date)
        • entry-content (post-content)
        • entry-footer (meta-bottom)
          • entry-meta alignright (alignright)
          • entry-meta alignleft (meta-bottom-left)
      • hentry...
    • loop-footer
      • loop-utility (paging)

Not all the elements from above structure examples were used since not all were needed. In the end, only three elements had to be added. The rest of the changes were simply modifying or adding classes to conform to the Loop Standard structure. For some elements, such as "date", the "date" class remained while also getting the "entry-meta" class. This makes it clear what type of structure it is while still giving the additional meaning of it being a container for the date.

Modifying a Theme to Use LoopBuddy

Here's an example of TwentyTen's index.php file before it begins loading the various templates:

<?php if ( ! dynamic_loop() ) : ?>
	<div class="loop">
		/* Run the loop to output the posts.
		 * If you want to overload this in a child theme then include a file
		 * called loop-index.php and that will be used instead.
		 get_template_part( 'loop', 'index' );
<?php endif; ?>

When dynamic_loop() is executed, LoopBuddy searches to see if this particular loop should be overridden. If not, the normal loop executes. If so, then LoopBuddy overwrites the content of the loop with LoopBuddy content.

Example of TwentyTen Using the Loop Standard

Here's an example TwentyTen Loop converted to using the Loop Standard

	<?php if ( have_posts() ) while ( have_posts() ) : the_post(); ?>

			<div class="loop-content">
				<div id="nav-above" class="navigation loop-utility loop-utility-above">
					<div class="nav-previous"><?php previous_post_link( '%link', '<span class="meta-nav">' . _x( '←', 'Previous post link', 'twentyten' ) . '</span> %title' ); ?></div>
					<div class="nav-next"><?php next_post_link( '%link', '%title <span class="meta-nav">' . _x( '→', 'Next post link', 'twentyten' ) . '</span>' ); ?></div>
				</div><!-- #nav-above -->

				<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
					<div class="entry-header">
						<h1 class="entry-title"><?php the_title(); ?></h1>
						<div class="entry-meta">
							<?php twentyten_posted_on(); ?>
						</div><!-- .entry-meta -->
					</div><!-- .entry-header-->
					<div class="entry-content">
						<?php the_content(); ?>
						<?php wp_link_pages( array( 'before' => '<div class="page-link">' . __( 'Pages:', 'twentyten' ), 'after' => '</div>' ) ); ?>
					</div><!-- .entry-content -->
					<div class="entry-footer">
<?php if ( get_the_author_meta( 'description' ) ) : // If a user has filled out their description, show a bio on their entries  ?>
						<div id="entry-author-info" class="entry-meta entry-meta-below">
							<div id="author-avatar">
								<?php echo get_avatar( get_the_author_meta( 'user_email' ), apply_filters( 'twentyten_author_bio_avatar_size', 60 ) ); ?>
							</div><!-- #author-avatar -->
							<div id="author-description">
								<h2><?php printf( esc_attr__( 'About %s', 'twentyten' ), get_the_author() ); ?></h2>
								<?php the_author_meta( 'description' ); ?>
								<div id="author-link">
									<a href="<?php echo get_author_posts_url( get_the_author_meta( 'ID' ) ); ?>">
										<?php printf( __( 'View all posts by %s <span class="meta-nav">→</span>', 'twentyten' ), get_the_author() ); ?>
								</div><!-- #author-link	-->
							</div><!-- #author-description -->
						</div><!-- #entry-author-info -->
<?php endif; ?>
						<div class="entry-utility">
							<?php twentyten_posted_in(); ?>
							<?php edit_post_link( __( 'Edit', 'twentyten' ), '<span class="edit-link">', '</span>' ); ?>
						</div><!-- .entry-utility -->
					</div><!-- .entry-footer-->
				</div><!-- #post-## -->
				<div class="loop-footer">
					<div id="nav-below" class="navigation loop-utility loop-utility-below">
						<div class="nav-previous"><?php previous_post_link( '%link', '<span class="meta-nav">' . _x( '←', 'Previous post link', 'twentyten' ) . '</span> %title' ); ?></div>
						<div class="nav-next"><?php next_post_link( '%link', '%title <span class="meta-nav">' . _x( '→', 'Next post link', 'twentyten' ) . '</span>' ); ?></div>
					</div><!-- #nav-below -->
				</div><!-- .loop-footer-->

				<?php comments_template( '', true ); ?>
			</div><!-- .loop-content-->

<?php endwhile; // end of the loop. ?>

After updating the template files, go through the theme's style.css file in order to update class references to match the new ones. Here are some basic replacements to make:

  • .page-title → .loop-title
  • .title → .entry-header
  • .post-title [h1, h2, h3, etc] (any instance of .post-title followed by a header tag) → .entry-title
  • .post-title → .entry-title
  • .post-meta → .entry-meta
  • .post-content → .entry-content
  • .meta-top → .entry-header
  • .meta-bottom → .entry-footer
  • .post → .hentry
  • .paging → .loop-utility

Showing LoopBuddy Theme Support

After you've modified your theme's loops, show LoopBuddy that your theme supports it by adding in the following line to your theme's functions.php file:

// Add support for the Loop Standard
add_theme_support( 'loop-standard' );


LoopBuddy allows you to create custom tags for the Layout editor. This is advanced functionality, so please don't attempt these steps if you are not intimately familiar with PHP and how LoopBuddy operates.

To create the custom tag, you must use the following hooks.

Creating a new Custom Tag

	add_filter( 'pb_loopbuddy_custom_tags', 'my_custom_tag_add' );
	function my_custom_tag_add( $custom_tags ) {
		//Always return $custom_tags
		$custom_tags[ 'start_wrap' ] = array( 
			'My Tag Label',
				'wrap' => 'div',
				'custom_class' => 'default class'
		return $custom_tags;	
	} //end my_custom_tag_add
	//Start off with the tag name, give the tag a label, and pass it which items it supports (all should ideally contain the 'wrap' and 'custom_class' items

Here are some built in tag items that you can choose from:

  • link_text
  • custom_url
  • custom_class
  • link_title
  • before_text
  • after_text
  • meta_key
  • max_width
  • max_height
  • shortcode
  • author_link_destination
  • user_profile
  • permalink
  • attachment_link_display
  • separator
  • text
  • date_format
  • comment_number_zero
  • comment_number_one
  • comment_number_more
  • post_date
  • bloginfo
  • content_more
  • url_display
  • image_size

Custom Tag Example

We have created an example plugin to add a custom tag.

Check out the LoopBuddy Marquee Plugin: File:Loopbuddy marquee.zip as an example of creating custom tags.

Creating a new custom tag item

add_filter( 'pb_loopbuddy_tag_items', 'my_custom_item_add' );
function my_custom_item_add( $loopbuddy_items ) {
	//Always return $loopbuddy_items
	$loopbuddy_items[ 'my_custom_item' ] = array( 
		'function' => 'callback_function',
		'args' => array(
			'label' => __( 'Link Text', 'LION' ),
			'tip' => __( 'Optional text for link.  Leave blank to use link as the text.', 'LION' ),
			'options' => array( 'option1', 'option2' )
	return $loopbuddy_items;
} //end my_custom_item_add

/* $settings are the arguments passed for the tag item and looks like this 
 [label] => HTML Wrapper
    [tip] => Choose which HTML element to wrap around the item
    [options] => Array
            [0] => none
            [1] => span
            [2] => div
            [3] => p
            [4] => h1
            [5] => h2
            [6] => h3
            [7] => h4
            [8] => h5
            [9] => h6

    [key] => wrap
    [settings] => Array
            [image_size] => thumbnail
            [max_width] => 
            [max_height] => 
            [wrap] => p
            [before_text] => 
            [after_text] => 
            [custom_url] => 
            [custom_class] => attachment
            [tag] => wp_get_attachment_image

function callback_function( $settings ) {
	$defaults = array(
		'key' => '',
		'label' => '',
		'tip' => false,
		'settings' => array(),
		'options' => array()
	extract( wp_parse_args( $settings, $defaults ) );
	//Output HTML for the item
} //end callback_function


Callback function for displaying the tag - pb_loopbuddy_tag_callback-{tag_name}

/*$settings contains the tag items and the tag item's value
		    [image_size] => thumbnail
		    [max_width] => 
		    [max_height] => 
		    [wrap] => p
		    [before_text] => 
		    [after_text] => 
		    [custom_url] => 
		    [custom_class] => attachment
		    [tag] => wp_get_attachment_image
//Add header code
add_action( 'pb_loopbuddy_tag_header-mytagname', 'my_custom_tag_header' );
function my_custom_tag_header( $settings ) {
	echo "my header, notes, or other code";
	//Render your tag based on its settings
} //end my_custom_tag_header

//Add footer code
add_action( 'pb_loopbuddy_tag_footer-mytagname', 'my_custom_tag_footer' );
function my_custom_tag_footer( $settings ) {
	echo "my footer, notes, or other code";
	//Render your tag based on its settings
} //end my_custom_tag_header

add_filter( 'pb_loopbuddy_tag_supports-mytagname', 'my_custom_tag_supports' );
//Return an array of what tag items the tag supports
function my_custom_tag_supports( $support_tag_items ) {
	return array( 'wrap', 'link_text', 'before_text', 'after_text', 'custom_class' );
	//Render your tag based on its settings
} //end my_custom_tag_supports

Rendering the Tag on the Front-end - pb_loopbuddy_render-{tag_name}

add_filter( 'pb_loopbuddy_render-mytagname', 'mytagname_frontend', 10, 2 );
function mytagname_frontend( $post_object, $tag_items ) {
	/* $tag_items look like this
    [wrap] => none
    [link_text] => Edit Post
    [before_text] => 
    [after_text] => 
    [custom_url] => 
    [custom_class] => 
    [tag] => edit_post_link
	$return = false; //Populate the $return variable
	$return = pluginbuddy_loopbuddy_render_slotitems::get_output( $return, $post_object, $tag_items, true ); //The last argument is skip_before text 
	return $return;
} //end mytagname_frontend

Suggestions / Bugs

  1. SUGGESTION - Currently when you add multiple tags to the same line in the Layout Editor, it displays them right next to each other WITHOUT a space. It would be beneficial if all tags automatically have a space after them so that users don't have to go add spaces themselves.
  2. The use of the "Use Current Post or Page ID" is a VERY important setting for LoopBuddy, maybe if we add an additional explanation or example to the help area.

Additional Resources

  1. Purchase BackupBuddy
  1. PluginBuddy Tutorials
  2. PluginBuddy.com
  3. Support Forums