Vista-Like Breadcrumbs for WordPress

applevista-breadcrumbs2

Update: This was modified on February 10, 2015 to reflect changes in suggested calling code for Breadcrumb NavXT. Note that the Breadcrumb NavXT Multidimension Extensions plugin handles the PHP side of things covered in the guide below.

Update: This was modified on January 11, 2011 to reflect changes in the code base of Breadcrumb NavXT. Note that this should now work for all newer versions of Breadcrumb NavXT (3.6.0 up to 4.0). It will not work for the proposed Breadcrumb NavXT 4.0.

Previously, one revealed how to apply Janko’s Apple.com-like breadcrumb trail tutorial to WordPress using Breadcrumb NavXT. After several requests for a breadcrumb trail a la the one found in Explorer since Windows Vista, this guide was created. While this guide will not provide a method to exactly recreate the Vista breadcrumbs, it will be in the same spirit. The Apple.com breadcrumb trail style will be extended; a simple replacement of images and minor CSS tweaking will result something behaving very similar to the vista breadcrumb trail.

Download sources | View Demo

Continue reading

Keep the Current Page Out of the Breadcrumb Trail

Note: This guide is only valid for versions of Breadcrumb NavXT prior to 4.0. Since Breadcrumb NavXT 4.0 the bcn_after_fill action should be used to remove breadcrumbs from the breadcrumb trail.

Over the past year, several individuals have inquired on the feasibility of removing the current item (page, post, etc) from the Breadcrumb trail. While this is not good form, every page in the hierarchy should be represented in the breadcrumb trail, one will discuss how to remove the current item from the breadcrumb trail.

As in the Keep a Page Out of the Breadcrumb Trail guide, the method discussed herein differs from earlier methods provided in response to comments elsewhere. Likewise, this method uses the OOP principle of inheritance and requires PHP5–as does Breadcrumb NavXT so that should not be a problem.

Previously, removing the current item from the breadcrumb trail was the suggested method of implementation. While this works great, it does have some flexibility issues. And, it will not work if the bcn_breadcrumb_trail::trail array is a private or protected member variable (which may happen in the future). Instead, this guide will override the bcn_breadcrumb_trail::display() member function.

First, open the functions.php file of your theme. Within it we are going to create a new class named ext_breadcrumb_trail, and tell PHP that it is an extension of the bcn_breadcrumb_trail class. We will place the skeleton for the class constructor in at this time as well.

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	//Default constructor
	function __construct()
	{
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
}

Now, onto overriding bcn_breadcrumb_trail::display(). If you do not use bcn_breadcrumb_trail::display_trail() then this is all you will need:

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	//Default constructor
	function __construct()
	{
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
	/**
	 * display
	 *
	 * Breadcrumb Creation Function
	 *
	 * This functions outputs or returns the breadcrumb trail in string form.
	 *
	 * @return void Void if Option to print out breadcrumb trail was chosen.
	 * @return string String-Data of breadcrumb trail.
	 * @param bool $return Whether to return data or to echo it.
	 * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not.
	 * @param bool $reverse[optional] Whether to reverse the output or not.
	 */
	function display($return = false, $linked = true, $reverse = false)
	{
		//Set trail order based on reverse flag
		$this->order($reverse);
		//Initilize the string which will hold the assembled trail
		$trail_str = '';
		//The main compiling loop
		foreach($this->trail as $key=>$breadcrumb)
		{
			//Must branch if we are reversing the output or not
			if($reverse)
			{
				//Add in the separator only if we are the 2nd or greater element
				if($key > 0)
				{
					$trail_str .= $this->opt['separator'];
				}
			}
			else
			{
				//Only show the separator when necessary
				if($key > count($this->trail) - 2)
				{
					$trail_str .= $this->opt['separator'];
				}
			}
			//Trim titles, if needed
			if($this->opt['max_title_length'] > 0)
			{
				//Trim the breadcrumb's title
				$breadcrumb->title_trim($this->opt['max_title_length']);
			}
			//We want to output everything but the current item
			if($key === 0)
			{
				break;
			}
			//Place in the breadcrumb's assembled elements
			$trail_str .= $breadcrumb->assemble($linked);
		}
		//Should we return or echo the assembled trail?
		if($return)
		{
			return $trail_str;
		}
		else
		{
			//Giving credit where credit is due, please don't remove it
			$tag = "<!-- Breadcrumb NavXT " . $this->version . " -->\n";
			echo $tag . $trail_str;
		}
	}
}

The above code has only minor changes from the distributed bcn_breadcrumb_trail::display() code. One line was adjusted so that one less breadcrumb separator would be output. The other change involved replacing $this->current_item($breadcrumb); with break;, ending the loop execution. Note, if you want the “extra” breadcrumb separator to still display, change the line:

if($key < count($this->trail) - 2)

to:

if($key < count($this->trail) - 1)

If you need bcn_breadcrumb_trail::display_trail() instead of bcn_breadcrumb_trail::display() you will want to use the following code:

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	//Default constructor
	function __construct()
	{
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
	/**
	 * display_list
	 *
	 * Breadcrumb Creation Function
	 *
	 * This functions outputs or returns the breadcrumb trail in list form.
	 *
	 * @return void Void if Option to print out breadcrumb trail was chosen.
	 * @return string String-Data of breadcrumb trail.
	 * @param bool $return Whether to return data or to echo it.
	 * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not.
	 * @param bool $reverse[optional] Whether to reverse the output or not.
	 */
	function display_list($return = false, $linked = true, $reverse = false)
	{
		//Set trail order based on reverse flag
		$this->order($reverse);
		//Initilize the string which will hold the assembled trail
		$trail_str = '';
		//The main compiling loop
		foreach($this->trail as $key=>$breadcrumb)
		{
			$trail_str .= '
<li>';
			//Trim titles, if needed
			if($this->opt['max_title_length'] > 0)
			{
				//Trim the breadcrumb's title
				$breadcrumb->title_trim(
					$this->opt['max_title_length']);
			}
			//We want to output everything but the current item
			if($key === 0)
			{
				break;
			}
			//Place in the breadcrumb's assembled elements
			$trail_str .= $breadcrumb->assemble($linked);
			$trail_str .= "</li>

\n";
		}
		//Should we return or echo the assembled trail?
		if($return)
		{
			return $trail_str;
		}
		else
		{
			//Giving credit where credit is due, please don't remove it
			$tag = "<!-- Breadcrumb NavXT " . $this->version . " -->\n";
			echo $tag . $trail_str;
		}
	}
}

The only change in this code from the distributed bcn_breadcrumb_trail::display_trail() involved modifying the branch statement used for the current item. This involved replacing $this->current_item($breadcrumb); with break;. Now onto calling our new class. For users of the normal, sting output breadcrumb trail, you will use something on the lines of:

if(class_exists('ext_breadcrumb_trail'))
{
	//Make new instance of the ext_breadcrumb_trail object
	$breadcrumb_trail = new ext_breadcrumb_trail();
	//Setup options here if needed
	//Fill the breadcrumb trail
	$breadcrumb_trail->fill();
	//Display the trail
	$breadcrumb_trail->display();
}

While users of the HTML list output form of the breadcrumb trail will want to use:

if(class_exists('ext_breadcrumb_trail'))
{
	//Make new instance of the ext_breadcrumb_trail object
	$breadcrumb_trail = new ext_breadcrumb_trail();
	//Setup options here if needed
	//Fill the breadcrumb trail
	$breadcrumb_trail->fill();
	//Display the trail
	$breadcrumb_trail->display_list();
}

This is a quite simple method for removing the current item from the breadcrumb trail output. Since the display functions will not be modified in the foreseeable future, this is quite safe to use. Again, for usability reasons, one recommends you do not actually remove the current item from the breadcrumb trail.

-John Havlik

[end of transmission, stay tuned]

Keep a Page Out of the Breadcrumb Trail

Note: This guide is only valid for versions of Breadcrumb NavXT prior to 4.0. Since Breadcrumb NavXT 4.0 the bcn_after_fill action should be used to remove breadcrumbs from the breadcrumb trail.

In the past, several users have asked how to exclude certain pages from the breadcrumb trail generated by Breadcrumb NavXT. As with most programming problems, many solutions exist to this problem. Previously, one posted code that removed the breadcrumb from the bcn_breadcrumb_trail::trail array before calling bcn_breadcrumb_trail::display(). However, since the introduction of Breadcrumb NavXT 3.0 a much better solution exists. This method uses the inheritance principle of OOP and requires no editing of the distributed files.

Code in this tutorial was written against the SVN Trunk version of Breadcrumb NavXT (the basis or Breadcrumb NavXT 3.3.0). Therefore, any code contained herein will require some modifications to work with Breadcrumb NavXT 3.2.x. The general process, however, is the same for any version of Breadcrumb NavXT since 3.0.0. Also, note that you must have a PHP5 environment for this to work as it requires the PHP5 object model.

First, open the functions.php file of your theme. Within it we are going to create a new class named ext_breadcrumb_trail, and tell PHP that it is an extension of the bcn_breadcrumb_trail class. We’ll place the skeleton for the class constructor in at this time as well.

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	//Default constructor
	function __construct()
	{
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
}

We need a way to get the IDs that will be excluded from the trail into the class. They could be hard coded into the class, but that is not very extensible (and a very bad coding practice). Instead, a public member variable named $excluded_ids will be added to store the IDs. Now, we should have the constructor accept IDs to exclude and store them in $excluded_ids. Our code now looks similar to the following:

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	public $excluded_ids = array();
	//Default constructor
	function __construct($excluded_ids)
	{
		//Set the value of
		$this->excluded_ids = $excluded_ids;
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
}

Now that the IDs of pages to be excluded can get into the class, we need to do something with them. We want to override the function bcn_breadcrumb_trail::page_parents() since it does not know how to exclude pages. To start, we’ll copy the code for page_parents from the class bcn_breadcrumb_trail into our new class. This is the result:

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	public $excluded_ids = array();
	function __construct($excluded_ids)
	{
		$this->excluded_ids = $excluded_ids;
		parent::__construct();
	}
	/**
	 * page_parents
	 *
	 * A Breadcrumb Trail Filling Function
	 *
	 * This recursive functions fills the trail with breadcrumbs for parent pages.
	 * @param  (int)   $id The id of the parent page.
	 * @param  (int)   $frontpage The id of the front page.
	 */
	function page_parents($id, $frontpage)
	{
		$parent = get_post($id);
		//Place the breadcrumb in the trail, uses the constructor
		$breadcrumb = $this->add(new bcn_breadcrumb(apply_filters('the_title', $parent->post_title), $this->opt['page_prefix'], $this->opt['page_suffix']));
		//Assign the anchor properties
		$breadcrumb->set_anchor($this->opt['page_anchor'], get_permalink($id));
		//Make sure the id is valid
		if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent)
		{
			//If valid, recursively call this function
			$this->page_parents($parent->post_parent, $frontpage);
		}
	}
}

Now, it’s time to modify the page_parents() function. We’ll use ext_breadcrumb_trail::excluded_ids and the PHP function in_array() to skip the breadcrumb insertion step for pages that are to be excluded from the trail. We do this by wrapping the two lines of code containing the variable $breadcrumb within a branch of an if statement. Within the if statement we’ll use $id and $this->excluded_ids as the parameters for in_array(). Since we want the branch to run if the ID is not an excluded ID, we’ll place the not operator (!) in front of in_array. At this point, we have the final version of our class that is ready to use.

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	public $excluded_ids = array();
	function __construct($excluded_ids)
	{
		$this->excluded_ids = $excluded_ids;
		parent::__construct();
	}
	/**
	 * page_parents
	 *
	 * A Breadcrumb Trail Filling Function
	 *
	 * This recursive functions fills the trail with breadcrumbs for parent pages.
	 * @param  (int)   $id The id of the parent page.
	 * @param  (int)   $frontpage The id of the front page.
	 */
	function page_parents($id, $frontpage)
	{
		$parent = get_post($id);
		//Check if the current page should be excluded
		if(!in_array($id, $this->excluded_ids))
		{
			//Place the breadcrumb in the trail, uses the constructor
			$breadcrumb = $this->add(new bcn_breadcrumb(apply_filters('the_title', $parent->post_title), $this->opt['page_prefix'], $this->opt['page_suffix']));
			//Assign the anchor properties
			$breadcrumb->set_anchor($this->opt['page_anchor'], get_permalink($id));
		}
		//Make sure the id is valid
		if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent)
		{
			//If valid, recursively call this function
			$this->page_parents($parent->post_parent, $frontpage);
		}
	}
}

Next, we need to modify the breadcrumb trail calling code in the theme. Assuming that the theme directly calls the bcn_breadcrumb_trail class, very little has to be modified. We just replace all instances of bcn_breadcrumb_trail with ext_breadcrumb_trail in the calling code. Additionally, when creating the new instance of ext_breadcrumb_trail we need to feed in our array of IDs of pages to be excluded. An example calling code block is located below, in it pages with ID equal to 100, 230, or 231 will not show up in the breadcrumb trail except when they are the current page.

if(class_exists('ext_breadcrumb_trail'))
{
	//Make new instance of the ext_breadcrumb_trail object
	$breadcrumb_trail = new ext_breadcrumb_trail(array(100,230,231));
	//Setup options here if needed
	//Fill the breadcrumb trail
	$breadcrumb_trail->fill();
	//Display the trail
	$breadcrumb_trail->display();
}

In this tutorial we never modified any of the actual plugin files. This was made possible due to inheritance through the creation of a derived class. Since no plugin files were modified, upgrading to new versions of Breadcrumb NavXT are less likely to break the functionality. Finally, this method can easily be modified to exclude categories instead of pages from the breadcrumb trail (replace page_parents with category_parents).

-John Havlik

[end of transmission, stay tuned]