September 17, 2009

jQuery UI Tabs for BuddyPress Member profiles

Filed under: Wordpress — Tags: , , , , — Jayx @ 6:43 pm

Disclaimer: I would like to state (for the record) that I am not a programmer by any stretch of the imagination (I live on XHTML/CSS) and that the method below would not have been possible for me to implement without the help of two of my good programmer friends – Nielo and Stii … thanks – you guys rock (but then you already knew that). I have to point out that I have a firm grasp of the principles, it’s just my syntax mastery that is severely lacking, so the method is all mine, the code … not necessarily so.

Anyhow … to the point of this post. It would seem that one of the most requested features for BuddyPress, is a means of dividing (or at the very least being able to select individually) the member profile info groups. I needed to do this and also create a simple navigation to the profile groups, so my solution had two components.

First let’s start with the default member profile loop (found at wp-content/bp-themes/your-member-theme-/profile/profile-loop.php) …

<?php if ( bp_has_profile() ) : ?>
	<?php while ( bp_profile_groups() ) : bp_the_profile_group(); ?>

		<?php if ( bp_profile_group_has_fields() ) : ?>
			<div class="info-group">
				<h4><?php bp_the_profile_group_name() ?></h4>

				<table class="profile-fields">
				<?php while ( bp_profile_fields() ) : bp_the_profile_field(); ?>

					<?php if ( bp_field_has_data() ) : ?>
					<tr<?php bp_field_css_class() ?>>
						<td class="label">
							<?php bp_the_profile_field_name() ?>
						</td>
						<td class="data">
							<?php bp_the_profile_field_value() ?>
						</td>
					</tr>
					<?php endif; ?>

				<?php endwhile; ?>
				</table>
			</div>
		<?php endif; ?>	

	<?php endwhile; ?>

	<div class="button-block">
		<?php if ( bp_is_home() ) : ?>
			<?php bp_edit_profile_button() ?>
		<?php endif; ?>
	</div>

<?php else: ?>

	<div id="message" class="info">
		<p><?php _e( 'Sorry, this person does not have a public profile.', 'buddypress' ) ?></p>
	</div>

<?php endif;?>

As should be obvious, the loop just returns another div.info-group for every profile group that has at least one field completed by the user, but offers us no hooks – so we need to add an ID to each profile group. This will allow us to target individual elements later in the script. What I’ve done is to call the bp_profile_group_name and then use the WordPress sanitize_title function to create a valid ID from the group name … the loop needs to change to this:

<?php while ( bp_profile_groups() ) : bp_the_profile_group(); ?>
	<?php global $group;?>
	<?php if ( bp_profile_group_has_fields() ) : ?>
		<div id="<?php echo sanitize_title($group->name);?>" class="info-group">
			<table class="profile-fields">
			<?php while ( bp_profile_fields() ) : bp_the_profile_field(); ?>

				<?php if ( bp_field_has_data() ) : ?>
				<tr<?php bp_field_css_class() ?>>
					<td class="label">
						<?php bp_the_profile_field_name() ?>
					</td>
					<td class="data">
						<?php bp_the_profile_field_value() ?>
					</td>
				</tr>
				<?php endif; ?>

			<?php endwhile; ?>
			</table>
		</div>
	<?php endif; ?>

<?php endwhile; ?>

Each profile group will now have an ID, which thus far is pretty useless unless you just want to style each profile group differently, but it should be apparent that we can now use the hooks as named anchors (part of the solution for making those UI Tabs) and navigate to those profile groups.

The method I used for the UI Tabs comes straight from jQuery for designers (a brilliant resource by the way). Bear in mind that WordPress already loads jQuery, so no wp_enqueue_script required (well not in my experience in this implementation) – I used the script inline thus:

<script type="text/javascript" charset="utf-8">
	jQuery(function () {
	    var tabContainers = jQuery('div.tabs > div');

	    jQuery('div.tabs ul.tabNavigation a').click(function () {
	        tabContainers.hide().filter(this.hash).show();

	        jQuery('div.tabs ul.tabNavigation a').removeClass('selected');
	        jQuery(this).addClass('selected');

	        return false;
	    }).filter(':first').click();
	});
</script>

The only change that had to be made was to change “$” to “jQuery” throughout the script (thanks Stii – well spotted). Now all we need do is to add the navigation, which you can do manually with an unordered list; although my preference was again for something a bit more dynamic, because the page looked a bit flimsy when a member has not completed all the additional fields in their profile info.

I basically duplicated the loop and stripped it out to end up with just enough markup for a menu that only returns links for items that has data in them. That loop looks like this:

<ul class="tabNavigation">
	<?php while ( bp_profile_groups() ) : bp_the_profile_group(); ?>
	<?php global $group;?>
		<?php if ( bp_profile_group_has_fields() ) : ?>
			<li><a href="#<?php echo sanitize_title($group->name);?>"><?php bp_the_profile_group_name() ?></a></li>
		<?php endif; ?>
	<?php endwhile; ?>
</ul>

All that is left for us to do now, is to wrap both loops in a container (div.tabs for preference) for the JavaScript to sort itself out and style the navigation to taste. If you are using the above loop for the navigation as opposed to a static option, you can remove global $group from the second loop – it only needs to be set once.

For those who are not to keen on figuring this out for yourself and prefer the winning copy|paste recipe – here’s the complete loop as I have it … should work right out of the box, just overwrite everything in your profile-loop.php … enjoy :)

<script type="text/javascript" charset="utf-8">
	jQuery(function () {
	    var tabContainers = jQuery('div.tabs > div');

	    jQuery('div.tabs ul.tabNavigation a').click(function () {
	        tabContainers.hide().filter(this.hash).show();

	        jQuery('div.tabs ul.tabNavigation a').removeClass('selected');
	        jQuery(this).addClass('selected');

	        return false;
	    }).filter(':first').click();
	});
</script>
<div class="tabs">
<?php if ( bp_has_profile() ) : ?>

<ul class="tabNavigation">
	<?php while ( bp_profile_groups() ) : bp_the_profile_group(); ?>
	<?php global $group;?>
		<?php if ( bp_profile_group_has_fields() ) : ?>
			<li><a href="#<?php echo sanitize_title($group->name);?>"><?php bp_the_profile_group_name() ?></a></li>
		<?php endif; ?>
	<?php endwhile; ?>
</ul>
	<?php while ( bp_profile_groups() ) : bp_the_profile_group(); ?>
		<?php if ( bp_profile_group_has_fields() ) : ?>
			<div id="<?php echo sanitize_title($group->name);?>" class="info-group">
				<table class="profile-fields">
				<?php while ( bp_profile_fields() ) : bp_the_profile_field(); ?>

					<?php if ( bp_field_has_data() ) : ?>
					<tr<?php bp_field_css_class() ?>>
						<td class="label">
							<?php bp_the_profile_field_name() ?>
						</td>
						<td class="data">
							<?php bp_the_profile_field_value() ?>
						</td>
					</tr>
					<?php endif; ?>

				<?php endwhile; ?>
				</table>
			</div>
		<?php endif; ?>

	<?php endwhile; ?>

</div>
	<div class="button-block">
		<?php if ( bp_is_home() ) : ?>
			<?php bp_edit_profile_button() ?>
		<?php endif; ?>
	</div>

<?php else: ?>

	<div id="message" class="info">
		<p><?php _e( 'Sorry, this person does not have a public profile.', 'buddypress' ) ?></p>
	</div>

<?php endif;?>
spread the word
  • Google Bookmarks
  • muti
  • StumbleUpon
  • TwitThis
  • Facebook
  • Digg
  • laaik.it
  • del.icio.us
  • Technorati
  • Reddit

7 Comments »

  1. Hi Jayx,

    I came across your blogpost about implementing jQuery Tabs in your Buddypress install, and I found it very informative. We (me and some others from BP.org) are currently setting up a site dedicated to Buddypress tips and tricks;

    http://www.bp-tricks.com

    We are launching soon, and we would like to put this blogpost onto the website.. If you are interested in contributing, it would be awesome!

    Greetings,
    Bowe Frankema
    http://buddypress.org/developers/bowromir/

    Comment by Bowe — November 20, 2009 @ 7:41 pm

  2. Hi Bowe … this is for the community using open source code, so feel free to use this article on your site – a link back to the original post would be appreciated.

    Comment by Jayx — November 23, 2009 @ 9:30 am

  3. I can confirm that this works. It needs some styling, but besides it is a great piece of code, well done and thanks for sharing!

    Comment by jez — December 4, 2009 @ 10:23 am

  4. Thanks for commenting Jez … can you perhaps post a link to the website that you implemented this on – the one that I had to create this for is presently accessible to members only (and will be for some time).

    I would also like some feedback on the usage of this in a child theme (in other words if this still works if you just drop my file into the theme folder) as I haven’t had time to experiment with this.

    Comment by Jayx — December 4, 2009 @ 1:42 pm

  5. when you say “I used the script inline thus:” what do you mean? where should that be paged?

    Comment by vusi — January 9, 2010 @ 2:01 am

  6. aaahhh never mind. thanx for the great post

    Comment by vusi — January 9, 2010 @ 2:04 am

  7. Great tipps! Nice Thx!

    Comment by Brody — April 14, 2010 @ 5:15 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress. WP Classic Theme adapted by jayx. Valid XHTML 1.0 Transitional.