Hi,

Menu Firstchild is a module which allow to build menu items directly linked to their first child. This module brings 2 important issues on crumbs :

- when there are 2 items using path in the menu, the first is always used by crumbs to build the breadcrumb
- when this firstchilded item is shown in the breadcrumb, it is linked to "" instead of the first item's child

I hope this is not too confuse.
Regards,

Comments

donquixote’s picture

- when there are 2 items using path in the menu, the first is always used by crumbs to build the breadcrumb

What do you suggest as a criterion? Use the one with the highest depth? And lowest weight?
I think it already can distinguish between different menus, if you explicitly configure an order of menus in the crumbs configuration.

- when this firstchilded item is shown in the breadcrumb, it is linked to "" instead of the first item's child

This is probably because the database has "<firstchild>" as the link, and crumbs or the l() function does not know how to turn that into a link.

Do you know how menu_firtschild does it? Does it override theme_menu_item_link() ?

duaelfr’s picture

I do not have any solution for this issue and I do not know how menu firstchild is working in detail.

In my first point I was talking about many links using firstchild in the same menu. I already noticed that it is possible to choose menus priority but it is not my actual problem.

Let's see a common use case :
- A : => node/X
-- A1 : node/X
-- A2 : node/Y
- B : => node/Z
-- B1 : node/Z

On node/X page the breadcrumb will be "Home > A > A1" which is correct
On node/Z page the breadcrumb will be "Home > A > B1" which is wrong

donquixote’s picture

I can confirm the behavior you describe.
The problem is with the system path as the only key for each crumbs item, and the loop prevention logic that does not allow a system path to occur twice in the trail.
What we would need is a "disambiguator" added to the system path. And/or a special method like "findParentRec()", that fires in case of recursion.

This is quite complicated, I need to think about it.

donquixote’s picture

As an easier fix, I could simply skip the items that are firstchild, or that have an identical path to the child item.
Would this be acceptable?

The following situation would still not work:
Having a menu with
A
- X
-- B
--- X
---- C
the breadcrumbs should be
A > X > B > X > C

But Crumbs would stop when it finds the second X, assuming that it is an infinite loop.

duaelfr’s picture

Skipping is not the solution.

If you look at my previous sample.
On the node/Y page the breadcrumb should be "Home > A > A2" because A stands for A1

I hate breadcrumbs ^^

Is it possible to convert to its realpath and to check is it is the current object path or one of its siblings ?
Can Crumbs have access to mlids ? It would help for detecting infinite loop but only if once entered in menu process we cannot leave it.

donquixote’s picture

I have a solution in mind.

The original findParent() function does only return plain system paths or aliases, without any additional data. This also makes it impossible to have breadcrumbs based on the query string.

The solution I have in mind is to support an additional method, called sth like "findParentSpecial()", which would have a more complex API.

E.g.

class ...
  /**
   * Usual findParent()
   * (not executed, because findParentSpecial() exists)
   */
  function findParent($path, $item) {
    return 'path/to/parent';
  }

  /**
   * More powerful version of findParent()
   */
  function findParentSpecial($api, $path, $item) {
    if ($item['crumbs_meta']['menu:mlid'] == 123) {
      $api->setParent('path/to/parent');
      $api->setMeta('menu:mlid', 456);
    }
  }
}

I still want to keep the less powerful version around for the average case, for performance reasons.

Anyway, this is going to be more work, needs to be planned a bit.

donquixote’s picture

In the meantime, you could try to hack your way with the decorateBreadcrumb() method..
(that's not the nice way to do it, though)

duaelfr’s picture

Don't worry about me.
Breadcrumbs are a recurrent problem so I will drop firstchild for landing pages and I will keep a look on Crumbs for the next time ;)
If you solve this, you will be the king of the breadcrumbs' world !

Regards

donquixote’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev
dotoree’s picture

Issue summary: View changes

An easy way to fix this is with the theme_breadcrumb function inside your theme

/**
 * Implements theme_breadcrumb().
 */
function MYTHEME_breadcrumb($variables) {
  $breadcrumb = $variables['breadcrumb'];

  if (!empty($breadcrumb)) {
    // Provide a navigational heading to give context for breadcrumb links to
    // screen-reader users. Make the heading invisible with .element-invisible.
    $output = '<h2 class="element-invisible">' . t('You are here') . '</h2>';

    // Replace <firstchild> string in breadcrumbs with the actual link
    // from menu active trail
    $active_trail = menu_get_active_trail();
    $token = urlencode('<firstchild>');
    foreach($breadcrumb as $k => $v) {
      if (FALSE !== strpos($v, $token)) {
        $breadcrumb[$k] = str_replace($token, drupal_get_path_alias($active_trail[$k]['href']), $v);
        break; // Should be only one <firstchild>
      }
    }

    $breadcrumb_str = implode('<span class="crumbs-separator">/</span>', $breadcrumb);

    $output .= '<div class="breadcrumb">' . $breadcrumb_str . '</div>';
    return $output;
  }
}
aschmoe’s picture

Status: Active » Needs review
StatusFileSize
new2.65 KB

Here is a patch adding menu_firstchild support. Defined an additional special case like <nolink> called (predictably) <firstchild>.

Wasn't entirely sure what the "menu_CrumbsMonoPlugin_specialItems" class was meant to accomplish, but added the additional code in there as well. This may be unnecessary or even harmful... let me know :)

lmeurs’s picture

@aschmoe: Thanks for the patch, great job! Since it seems the Crumbs module has changed a lot since your patch (functions have been moved to other files), I applied the changes manually to the latest dev.

I too used the Special Menu Items implementation as an example and created specific page and title callbacks for the Menu Firstchild module implementation as well as a specific implementation of the crumbs_MonoPlugin_FindParentInterface class.

I removed your <nolink> fallback from crumbs_Router::getRouterItem() since it seemed to me that the 3rd fragment with the menu link ID always is defined when the page callback handle is crumbs_firstchild_menu_link_page.

Finally I altered theme_crumbs_breadcrumb_link as well so <firstchild> breadcrumbs are output as plain text instead of links, just as with <nolink> menu items. This is to prevent both the parent and child breadcrumbs from being output as active links when at the first child page.

donquixote’s picture

Finally I altered theme_crumbs_breadcrumb_link as well so breadcrumbs are output as plain text instead of links, just as with menu items.

I think we should rather set $item['href'] = '' for firstchild links, somewhere before it goes to theme_crumbs_breadcrumb_link().
This works better for existing theme overrides.

lmeurs’s picture

StatusFileSize
new4.71 KB
new2.08 KB

Thanks for the quick reply! I added an implementation of theme_preprocess_crumbs_breadcrumb_link() that sets the href attribute earlier, see patch attached.

Setting href to an empty value made the link refer to the front page. I think it's expected behavior that it links to the first child page, but to prevent the link from being rendered with the active class I chose to generate the absolute aliassed URL from the preprocess function instead of letting l() doing this. Or is this too hacky?

donquixote’s picture

Thinking about this again:
From a breadcrumb perspective, <firstchild> items should work the same as <nolink> items.
Having two links in the breadcrumb that link to the same page is confusing, not helpful. But having both items in there does make sense, because they have different link title, and each title carries useful information.
Therefore I would suggest to display the parent link as a span.

We can actually use the already-existing crumbs/special-menu-item/% route, and don't need to define something new.

donquixote’s picture

From a breadcrumb perspective, <firstchild> items should work the same as <nolink> items.

No, I'm on the wrong path here :)
An item with <firstchild> can have more children than just the first one. And for those other children, the solution in #15 would not work.

I still think we can reuse crumbs/special-menu-item/% for this.

donquixote’s picture

Have a look..

donquixote’s picture

donquixote’s picture

StatusFileSize
new2.37 KB
new618 bytes

Adding a function_exists().

Melissamcewen’s picture

I am using this on a UIC site and it is working well.