Git Product home page Git Product logo

breadcrumbs's Introduction

Build Status Latest Stable Version Total Downloads

Note on Laravel support

This repository was originally created as a package for Laravel 4, and included a service provider and a facade. Since that time, Laravel 5 came out, which uses slightly different techniques to handle packages. We've contemplated hacking something together to include support for both Laravel 4 and 5 in one package, or having separate branches for that, but in the end, opted for releasing a new major version of this package, 2.0.0, that doesn't depend on Laravel at all, and instead focuses on the core breadcrumbs functionality.

For Laravel support use one of the following packages:

This was done so as not to break backwards-compatibility for anyone - users with Laravel 4 apps can still depend on creitive/breadcrumbs:~1.0, and their apps will continue to work. However, the 1.0 version will receive no further updates, because the upgrade process should be real easy, and we urge everyone to do so:

composer remove creitive/breadcrumbs
composer require creitive/laravel4-breadcrumbs

This package reorganization also provides for a proper separation of concerns between packages, and enables others to make their own framework-specific integration packages, if they wish to do so.

Breadcrumbs

A simple breadcrumbs package. Generates Twitter Bootstrap-compatible output.

Installation

Just run this on the command line:

composer require creitive/breadcrumbs

Usage

The basic idea is to create an instance of the Creitive\Breadcrumbs\Breadcrumbs class somewhere in your app, and add crumbs using the provided methods described below. At a later time, you can just render the output somewhere (likely in a view, depending on your app infrastructure), which will generate Twitter Bootstrap-compatible HTML.

$breadcrumbs = new Creitive\Breadcrumbs\Breadcrumbs;

$breadcrumbs->addCrumb('Home', '/');

echo $breadcrumbs->render();

The rest of the documentation will assume you have a $breadcrumbs instance on which you are making calls.

Adding a crumb

$breadcrumbs->addCrumb('Home', '/');

The first argument is the title of the crumb, and the second one is that crumb's address. There are a few ways you can pass the address argument - if this argument begins with a forward slash, or a protocol (http/https), it will be treated as a complete URL, and the corresponding breadcrumb will link to it as-is. If it does not begin with either of those, it will be treated as a segment, and it will be appended to its previous breadcrumb.

Note: You can use also use add, which is an alias of addCrumb:

$breadcrumbs->add('Home', '/');

Example

$breadcrumbs->addCrumb('Home', '/');
$breadcrumbs->addCrumb('Pages', 'pages');
$breadcrumbs->addCrumb('Subpage', 'subpage');
$breadcrumbs->addCrumb('Subsubpage', '/subsubpage');
$breadcrumbs->addCrumb('Other website', 'http://otherwebsite.com/some-page');

echo $breadcrumbs->render();

The third breadcrumb ("Subpage") will link to /pages/subpage, building on the previous breadcrumb. However, the fourth breadcrumb will link to /subsubpage, because its address starts with a slash. The last breadcrumb will obviously link to the passed URL.

You can also chain calls to addCrumb in order to add multiple crumbs at once:

$breadcrumbs->addCrumb('Home', '/')
    ->addCrumb('Pages', 'pages')
    ->addCrumb('Subpage', 'subpage')
    ->addCrumb('Subsubpage', '/subsubpage')
    ->addCrumb('Other website', 'http://otherwebsite.com/some-page');

Note: In fact, method chaining is supported wherever possible, ie. all methods that aren't expected to have a specific return value: setBreadcrumbs(), addCrumb(), add(), setCssClasses(), addCssClasses(), removeCssClasses(), setDivider(), setListElement(), removeAll().

CSS classes

Three CSS class manipulation methods are at your disposal, each working more or less similarly:

$breadcrumbs->setCssClasses($classes);
$breadcrumbs->addCssClasses($classes);
$breadcrumbs->removeCssClasses($classes);

Each of these methods manipulates the classes which will be applied to the containing <ul> element. All of them may be passed either a string or an array. If passed a string, separate CSS classes should be separated with spaces.

$stringClasses = 'class1 class2 class3';
$arrayClasses = array('class4', 'class5');

$breadcrumbs->addCssClasses($stringClasses);
$breadcrumbs->addCssClasses($arrayClasses);

// All five classes will now be applied to the containing `<ul>` element.

It's also possible to configure a custom CSS class which will be applied to all list items:

$breadcrumbs->setListItemCssClass('breadcrumb-item');

Divider

The default breadcrumb divider is /, which is the default used by Twitter Bootstrap 2. If you'd like to change it to, for example, », you can just do:

$breadcrumbs->setDivider('»');

The dividers are rendered as <span>s with the divider CSS class. If you would like to use the new Bootstrap 3 HTML (which uses ::before CSS pseudo-element to style the separators), just set the divider to an empty string or null, and those elements will not be rendered at all in the HTML.

The List Element

The default list element used to wrap the breadcrumbs, is ul. To change it, use the setListElement method like so:

$breadcrumbs->setListElement('ol');

Last item as a link

By default, the last item in the list is not rendered as a link. If you wish to change this behavior, you can control it with the setLastItemWithHref() method, like this:

$breadcrumbs->setLastItemWithHref(true);

Of course, you can pass false if you wish to turn this behavior off later on, and you can check the current value of this setting with the getLastItemWithHref() method.

Output

Finally, when you actually want to display your breadcrumbs, all you need to do is call the render() method on the instance:

echo $breadcrumbs->render();

Note: You can also just echo the instance like this:

echo $breadcrumbs;

Note that crumb titles are rendered without escaping HTML characters, which was designed for flexibility, allowing you to use, say, <img> elements as breadcrumbs. This means that you should escape any text-content yourself when adding crumbs:

$breadcrumbs->addCrumb('<img src="/images/foo.png">', '/foo');
$breadcrumbs->addCrumb(htmlspecialchars($userSubmittedName), 'bar');

The output contains microdata markup - see Google's Structured Data documentation on breadcrumbs for more info.

Best Practices

To minimize code-duplication, this section will offer some tips on how to organize your breadcrumb handling. As this package was first developed internally for our in-house CMS, it is largely based on how we already handled breadcrumbs. These tips will assume that the project is based on Laravel 4, but it isn't hard to generalize them to any framework you might be using, as most have a similar organization of controllers.

So, we usually have a single BaseController which all other controlers extend. Any controller that does something in its constructor is required to call parent::__construct() first, so BaseController::__construct() is used to setup some basic configuration which is available to all other controllers from that point.

Note that the BaseController doesn't have any actions (ie. no routes call BaseController) - it's literally there to provide a base for all other controllers.

In BaseController::__construct(), we usually (among other things) store a breadcrumbs instance in the class, to make it available to subclasses, and call something like $this->breadcrumbs->addCrumb('Home', '/'), which basically adds a first breadcrumb called "Home", which links to the website root - thus, all pages will always have this breadcrumb first (assuming they render breadcrumbs in their views):

public function __construct()
{
    parent::__construct();

    $this->breadcrumbs = new \Creitive\Breadcrumbs\Breadcrumbs;
    $this->breadcrumbs->addCrumb('Home', '/');
}

Say we have a StoreController that lists various stores available on the website. Of course, this controller extends the BaseController, so its constructor might look something like this:

public function __construct()
{
    parent::__construct();

    $this->breadcrumbs->addCrumb('Stores', 'stores');
}

Now let's say we have an action getStores (which lists available stores), and getStore (which lists a single store's homepage). StoreController::getStores() wouldn't need to add a breadcrumb of its own, since it is already added in that controller's constructor, under the assumption that all of that controller's actions will have that crumb.

Naturally, StoreController::getStore() would do something like $this->breadcrumbs->addCrumb($store->name, $store->slug), so as to add that store's slug as the next breadcrumb.

Rendering the breadcrumbs at this point would yield HTML similar to the following (skipping the ul, li and divider elements for brevity):

<a href="/">Home</a>
<a href="/stores">Stores</a>
<a href="/stores/foo-store">Foo Store</a>

If the system has an admin panel, there is probably no use there for the "Home" breadcrumb added in BaseController::__construct(). We usually solve this by having an Admin\BaseController (which extends BaseController, has no actions, and all administrative controllers extend it), and do something like this in its constructor:

public function __construct()
{
    parent::__construct();

    $this->breadcrumbs->removeAll();
    $this->breadcrumbs->addCrumb('Home', '/admin');
}

Now a controller like Admin\StoreController (which extends Admin\BaseController) can do $this->breadcrumbs->addCrumb('Stores', 'stores') in its constructor (after calling parent::__construct() of course), to add its own breadcrumb.

For a bit more complex application, we tend not to hardcode routes like that all over the place, so we'll probably do stuff like:

$this->breadcrumbs->addCrumb(Lang::('pages.home'), URL::action('HomeController@getIndex'));
$this->breadcrumbs->addCrumb(Lang::('pages.stores'), URL::action('StoreController@getStores'));
$this->breadcrumbs->addCrumb($store->name, URL::action('StoreController@getStore', array('storeId' => $store->id)));

This is a bit out of the scope of this package's documentation, though, so we won't elaborate much more on that, since it extends into a more general explanation of how to organize your application (and assumes access to some of Laravel's infrastructure, which enables us to generate URLs based on the defined application routes).

Recommended CSS

This plugin uses the breadcrumbs CSS class on the containing ul element by default, which is what we used in our in-house CSS framework. Bootstrap uses breadcrumb by default, so if you're using Bootstrap's CSS, you should configure it with $this->breadcrumbs->setCssClasses('breadcrumb'), for example in BaseController::__construct().

Additionaly, the package will always add the class active to the last li element (which contains the last breadcrumb added), and a span element with a divider class will be rendered between all breadcrumbs.

If you're looking for some bare minimum CSS needed to get breadcrumbs working, you can use the code suggested by @SaintPeter in issue #6 of this project's issue tracker:

.breadcrumbs {
    list-style: none;
    overflow: hidden;
}

.breadcrumbs li {
    float: left;
}

Further Thoughts and Alternatives

This package is intended for very basic and simple breadcrumb handling, and it's something we've used for a long time, though initially not with Laravel.

We have considered upgrading it with advanced functionality, like supporting breadcrumb configuration, along with being able to reference parent breadcrumbs or use closures, or being able to define your own views for rendering, but we have decided against all that.

There is already a very powerful breadcrumbs package that does most of that - https://github.com/davejamesmiller/laravel-breadcrumbs - we highly recommend this package for complex projects, and we use it ourselves. If you're looking for alternatives, we've found another package available at https://github.com/noherczeg/breadcrumb but we haven't tried that one.

License

The code is licensed under the MIT license, which is available in the LICENSE file.

breadcrumbs's People

Contributors

ceesvanegmond avatar crissi avatar fuhrmann avatar hmil avatar lboynton avatar levacic avatar lukamacun avatar nelson6e65 avatar piperone avatar quentinbontemps avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

breadcrumbs's Issues

Add config file support for Laravel

We should have a config file where some default stuff like the listElement can be configured, and the service provider will automatically set that on the shared instance, so that the users may change this stuff via a configuration setting, rather than having to manually set it in code.

suggestion: Add support for chaining 'addCrumb' method.

1️⃣ It should be nice if we can chain methods like:

<?php
$breadcrumbs->addCrumb('Home', '/')
    ->addCrumb('Pages', 'pages')
    ->addCrumb('Subpage', 'subpage')
    ->addCrumb('Subsubpage', '/subsubpage')
    ->addCrumb('Other website', 'http://otherwebsite.com/some-page');
?>

I think is not hard to implement, it just need return $this in addCrumb method.

2️⃣ And, maybe, refactorize addCrumb name to add (shortest name) or add it as an alias:

<?php
$breadcrumbs->add('Home', '/')
    ->add('Pages', 'pages')
    ->add('Subpage', 'subpage')
    ->add('Subsubpage', '/subsubpage')
    ->add('Other website', 'http://otherwebsite.com/some-page');
?>

"Best Practices" for using this add on?

It would be helpful to show some simple "Best Practices" for using this plugin. I think I understand, in general, how it works, but it would be nice to see where the obvious places to put the components are. At least, it's not obvious to me where to put them.

I'm looking for where to place them to minimize duplication of code and simplify build-out.

Update defaults for Twitter Bootstrap 3

When this library was created, Twitter Bootstrap was at version 2, so the default divider element / was used. Twitter Bootstrap 3 uses pseudo elements for this, so it's not needed anymore, and should default to null (so it isn't even rendered at all). We should also update the default breadcrumbs class to be just breadcrumb instead (which is the Bootstrap class in both 2 and 3 - not sure why we didn't use that from the start).

In fact, since pseudo-elements are the "correct" way to do this (there's nothing semantic about having a divider in HTML, at least in my opinion), we should likely just remove the divider functionality.

As both of these (removing dividers and changing the default CSS class) are BC breaks, we won't do this before v4.0.0. Not sure when that's gonna happen, but I'll let this issue stay here so we don't forget about it.

If anyone has any input on this (or a good argument on why it shouldn't be done), feel free to comment!

Bootstrap changes

http://getbootstrap.com/components/#breadcrumbs
As indicated in the URL above, Bootstrap now uses an ol-element with the class "breadcrumb" (singular) for the breadcrumbs-component. As far as I can tell, there are no config-options for changing the containing html tag in this package.

Do you plan on updating the package so that it is once again Bootstrap-compatible?

Thanks!

Mention microdata markup support

Currently, the microdata markup generated thanks to #15 isn't mentioned anywhere in the documentation - but it would probably be useful for people to know about it, so we should add it somewhere to the README file.

http://schema.org/BreadcrumbList to "https"

Hello,

In the render() method, we find http and not https. Could you modify or can we override the method and how?

Thanks

public function render()
    {
        if (empty($this->breadcrumbs)) {
            return '';
        }

        $cssClasses = implode(' ', $this->breadcrumbsCssClasses);

        return '<'. $this->listElement . ' itemscope itemtype="http://schema.org/BreadcrumbList"'
                .' class="' . $cssClasses .'">'
                . $this->renderCrumbs()
                . '</'. $this->listElement .'>';
    }

Laravel 5.0

Problem 1

  • Installation request for creitive/breadcrumbs dev-master -> satisfiable by creitive/breadcrumbs[dev-master].
  • Conclusion: remove laravel/framework 5.0.x-dev
  • creitive/breadcrumbs dev-master requires illuminate/support 4.x -> satisfiable by illuminate/support[4.0.x-dev, 4.1.x-dev, 4.2.x-dev].
  • don't install illuminate/support 4.0.x-dev|don't install laravel/framework 5.0.x-dev
  • don't install illuminate/support 4.1.x-dev|don't install laravel/framework 5.0.x-dev
  • don't install illuminate/support 4.2.x-dev|don't install laravel/framework 5.0.x-dev
  • Installation request for laravel/framework ~5.0 -> satisfiable by laravel/framework[5.0.x-dev].

List Item Classes and Bootstrap 4

Hi,

There is currently no way to configure classes for list items generated breadcrumbs. I don't think a PR is needed, but if your goal is to support bootstrap or other css frameworks, it might be helpful to add a setListItemClass method similar to setCssClasses so that you can add default classes to the actual list breadcrumb li's.

For example, bootstrap 4 uses the following markup:

<ol class="breadcrumb">
  <li class="breadcrumb-item"><a href="#">Home</a></li>
  <li class="breadcrumb-item"><a href="#">Library</a></li>
  <li class="breadcrumb-item active">Data</li>
</ol>

Currently, the only class that is added to li's is active. I've manually added breadcrumb-item in my copy of this, but I think others would appreciate this as an option.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.