Menu | Affichage seulement des sous-menus [resolu]

Information importante

En raison d'un grand nombre d'inscriptions de spammers sur notre site, polluant sans relache notre forum, nous suspendons la création de compte via le formulaire de "sign up".

Il est néanmoins toujours possible de devenir adhérent•e en faisant la demande sur cette page, rubrique "Inscription" : https://www.drupal.fr/contact


De plus, le forum est désormais "interdit en écriture". Il n'est plus autorisé d'y écrire un sujet/billet/commentaire.

Pour contacter la communauté, merci de rejoindre le slack "drupalfrance".

Si vous voulez contacter le bureau de l'association, utilisez le formulaire disponible ici, ou envoyez-nous un DM sur twitter.

Bonjour à tous, je viens demander votre aide sur l'affichage de menu, qui ne peux passer que par du code je pense.

J'ai ma liste de Primary links :
P1 - P2 - P3 -P4

Ces 4 Primary links dans leur bloc sont affichés dans l'entête de la page.

Chaque Primary link entraine des sous menus :

sous-menu P1 / sous-menu P2 etc (avec eux même des sous menus possibles)

Cette liste s'affiche dans le bloc navigation à gauche.

Mon problème est qu'il répète toute la liste des menus avec les Primary links, et les sous menus.

J'aimerai que lorsque'on clique sur un primary links dans l'entête, a gauche apparaisse seulement la liste de ses sous-menus déroulé.

J'espère que je suis clair.
Je voulais modifier la fonction menu_tree() directement mais je n'y arrive pas.

Merci de votre aide

Forum : 
Version de Drupal : 

Le mieux est de créer un module ou un bloc personnalisé qui n'affiche que le menu local (défini comme celui de niveau 2 sous le "primary link" qui correspond à la page courante).

Comment est affiché le bloc "Navigation" ?

Pour cela, nous allons essayer de créer un bloc personnalisé. Notre point de départ : la fonction menu_block() du module "menu", qui se charge d'afficher le menu de navigation "normal". L'affichage du bloc dans cette fonction se fait ainsi :

<?php
 $item
= menu_get_item($delta);
 
$data['subject'] = check_plain($item['title']);
 
$data['content'] = theme('menu_tree', $delta);
 return
$data;
?>

La fonction centrale est en fait theme('menu_tree', $delta) qui execute, par défaut, la fonction theme_menu_tree(). Cette fonction affiche un arbre de menu. Le paramètre $delta est ici simplement le numéro d'item du menu (ou $mid) du menu parent. Par défaut, le $mid du menu "Navigation" est "1".

Reproduisons le bloc navigation de base

Dans "Construction du site" / "Bloc", on ajoute un bloc. Format d'entrée "PHP", pour pouvoir coder quelque chose. Pour afficher exactement la même chose que le bloc "Navigation", on rentrerait, sur le modèle ci-dessus, le simple bout de code suivant :

<?php
 
echo theme('menu_tree', 1);
?>

Résoudre enfin notre problème

Pour créer un bloc qui n'affiche que le "primary menu" de base, il nous faut d'abord déterminer l'item de menu actif. Pour cela, nous allons d'abord charger le "primary menu" :

<?php
 $item
= menu_get_item(variable_get('menu_primary_menu', 0));
?>

Puis nous allons parcourir les enfants de cet item de menu (ie. les éléments tout en haut du "primary menu") pour trouver celui qui est actif. En language Drupal, on appelle cela être "sur la piste active" (in active trail), c'est à dire être le parent du menu actif :

<?php
 $active_mid
= 0;
 foreach(
$item['children'] as $child_id) {
  if (
menu_in_active_trail($child_id)) {
   
$active_mid = $child_id;
    break;
  }
 }
?>

Enfin, il ne nous reste plus qu'à afficher les enfants du menu actif :

<?php
 
if ($active_mid) echo theme('menu_tree', $active_mid);
?>

Récapitulons

Au final, notre bloc utilise donc le code suivant :

<?php
 $item
= menu_get_item(variable_get('menu_primary_menu', 0));
 
$active_mid = 0;
 foreach(
$item['children'] as $child_id) {
  if (
menu_in_active_trail($child_id)) {
   
$active_mid = $child_id;
    break;
  }
 }
 if (
$active_mid) echo theme('menu_tree', $active_mid);
?>

Et voila :)

Hello,

Est-ce la seule façon de faire ?

La solution de damz est impecc, mais pas hyper facile à mettre en oeuvre pour un débutant. Vu que la demande de cet utilisateur doit être assez répandue (bcp de sites utilisent le modèle de navigation qu'il décrit), n'y a-t-il pas un autre moyen ? Par exemple, n'a-t-on pas un bloc généré automatiquement avec les "secondary links" (et ensuite, on règle Drupal de sorte que "secondary links" puise ces liens dans "primary links") ?

C'est une bonne idée. Malheureusement, si on peut créer un bloc pour un menu (donc pour celui désigné comme "Primary Links"), on ne peut pas créer de bloc pour les primary & secondary links en tant que tels.

De plus, si c'était le cas, ces menus s'afficheraient deux fois sur le thème (ie. une fois au niveau des secondary links et une fois dans un bloc). Et cela fait perdre en outre la possibilité d'avoir d'autres liens en tant que secondary links (comme par exemple les liens en bas de page sur ce site).

Donc je ne pense pas vraiment qu'il y ait d'autres méthodes. Mais tu as raison sur le fond, ce mode de navigation est tellement courant qu'il faudrait prévoir un module pour faire cela.

D'ailleur, j'ai trouvé sur d.o une solution plus économe, qui s'appuie sur le fait que Drupal a déjà calculé la piste active lorsqu'il affiche le bloc :

<?php
// get the menu items that lead to the current menu item
$active_trail =_menu_get_active_trail();
         
// get the menu id of the active top-level link
$mid = $active_trail[0];
         
// get the primary menus id
$pmid = variable_get('menu_primary_menu', 0);
           
//do they match?          
if ($active_trail[0] == $pmid)
  echo
theme('menu_tree', $active_trail[1]);
?>

Cela évite l'itération sur le menu primaire, mais le principe reste identique.

Salut,

Je vient justement de poster sur drupal.org deux modules qui réalisent cette fonctionnalité.

Le menu désiré est sectionné en un bloc par profondeur, puis chaque bloc est disponible dans la section d'administration des bloc, il n'y a plus qu'a les placer (simple comme bonjour !).

le module "Sliced Menu" s'attaque aux menus standards et "Sliced Book Navigation" permet la même chose mais avec la navigation d'un livre.

A noter qu'il faut définir le menu ou book à prendre en compte dans la section admin des modules.

Hello alwex,

Je suis très intéressé par l'utilisation de ton module que je suis déja en train de tester. L'as-tu essayé avec du multi-langue?

Comment doit-on faire pour modifier le template de ces block? Peut-on appliquer un template différent selon le niveau?

Merci!

Salut Adri,

Au niveau du multi-langue, je ne sais pas encore.

Les blocs sont tout à fait personalisable via CSS, chaque bloc possédant une classe différents en fonction de son niveau.

<ul class="book_block_1">
.
.
</ul>

<ul class="book_block_2">
.
.
</ul>

ect...

Le module Sliced Book Navigation est utilisé sur ce site :
http://groovnco.free.fr

Comme tu peu le voir, une partie de la navigation est à gauche et l'autre sous forme d'onglet au dessous des titres des pages.