Thème de menu avancé dans Drupal 7

15

J'ai navigué sur le Web et il n'est pas du tout évident de créer un thème pour les menus personnalisés. J'ai cherché pendant des heures et je n'ai pas trouvé un seul post qui illustre le processus, du début à la fin, de la création d'un menu et de la personnalisation de sa sortie. Il semble que ce soit un processus en plusieurs étapes:

  1. Créez le menu via l'interface Drupal.
  2. Créez une fonction de thème dans votre template.phpfichier pour thème la sortie.
  3. Exposez ce menu à un fichier de modèle (en quelque sorte) en l'ajoutant en tant que variable.
  4. Appelez la themefonction dans le menu du fichier modèle.

1 est assez facile à faire, les problèmes que je rencontre sont avec 2, 3 et 4. En regardant le modèle de page par défaut, je vois qu'il expose le menu principal dans la variable $main_menu. Plus tard dans la page, vous pouvez voir la fonction theme('links__system_main_menu', array('links' => $main_menu..., ce qui signifie qu'elle cherche quelque part une fonction de thème correctement nommée et l'utilise pour générer la sortie.

Je sais que si je place function theme_links__system_main_menu(&$variables) {...}dans mon fichier template.php Drupal utilisera cette fonction par opposition à function theme_menu_links(&$variables) {...}.

Ce que je ne sais pas, c'est comment Drupal relie le menu personnalisé que j'ai créé avec cette fonction. Disons par exemple que j'ai créé un menu appelé My Menu. Puis-je créer la fonction suivante dans mon template.phpfichier et thème la sortie pour ce menu?function theme_links__system_my_menu(&$variables) {...}

De plus, comment rendre ce menu personnalisé disponible dans un fichier modèle? Comment Drupal expose-t-il la $main_menuvariable à page.tpl.php?

Je pense que la clé qui me manque ici est de savoir comment intégrer la variable qui représente mon menu personnalisé dans une page de modèle. Pour la plupart, je suis complètement perdu avec ce que je dois faire après avoir créé le menu.

Merci pour l'aide.

EDIT: Je devrais probablement publier ce que je fais. Par mon commentaire à BetaRide ci-dessous, j'ai besoin d'injecter du HTML personnalisé dans les <li>éléments des éléments de menu. Plus précisément, j'ajoute des icônes Twitter Bootstrap.

Lester Peabody
la source

Réponses:

13

L'implémentation des menus par Drupal est un peu spéciale, elle ne fonctionne pas toujours comme elle le devrait.

Vous pouvez jeter un œil à l'implémentation principale de template_preprocess_page () pour voir comment les liens du menu principal sont ajoutés en tant que variable au modèle de page. Vous devez explorer un peu les documents de l'API, mais la fonction que vous souhaitez appeler dans votre implémentation de theme_preprocess_page () est menu_navigation_links () , qui renverra un tableau de liens dans le menu.

En regardant la ligne 106 du fichier page.tpl.php de Drupal core , vous pouvez voir comment les liens du menu principal sont thématisés dans le modèle en appelant la fonction theme ( ) avec un crochet de 'links__system_main_menu'.

Théoriquement, cette implémentation devrait pouvoir être dupliquée avec un menu personnalisé en suivant les conventions de dénomination standard. Ainsi, dans template.php, vous pourriez avoir:

function THEMENAME_preprocess_page(&$variables){
  $variables['custom_menu'] = menu_navigation_links('menu-custom-menu');
}

function THEMENAME_links__menu_custom_menu(&$variables){
 //custom theme function here
}

et dans page.tpl.php, vous ajouteriez quelque chose comme ceci:

<?php print theme('links__menu_custom_menu', array('links' => $custom_menu, 'attributes' => array('id' => 'custom-menu', 'class' => array('links', 'inline', 'clearfix')), 'heading' => t('Custom menu'))); ?>

Cependant, l'ajout du menu personnalisé en tant que variable sur votre modèle de page n'est pas nécessaire. Vous pouvez facilement placer le bloc du menu personnalisé dans une région souhaitée via l'interface d'administration Drupal. En outre, vous pouvez modifier les paramètres du site pour la source du menu principal , en remplaçant efficacement la variable par défaut $ main_menu dans page.tpl.php par votre menu personnalisé.

EDIT: Je vois juste votre ajout à propos de votre objectif final qui consiste simplement à ajouter du code HTML personnalisé aux éléments de menu des icônes. Selon la façon dont vous ajoutez ces icônes, il existe différentes options de module Drupal.

Icônes de menu - vous permet de télécharger une image via les paramètres de l'élément de menu et génère automatiquement CSS (personnalisable via un modèle) qui ajoute l'image comme arrière-plan sur l'élément de menu.

Attributs de menu - vous permet d'ajouter une classe personnalisée à chaque élément de menu via ses paramètres dans l'admin. Une fois qu'une classe unique est ajoutée à chaque élément de menu, vous pouvez utiliser CSS pour ajouter une icône à l'élément de menu ou utiliser javascript pour injecter le code HTML supplémentaire dans l'élément de menu.

sheena_d
la source
Cela semble répondre parfaitement à toutes mes questions. C'est une excellente réponse. Je vais essayer ça immédiatement.
Lester Peabody
1
Cela a fonctionné, mais j'ai pris à cœur l'opinion unanime de tous et je n'ai pas utilisé cette méthode. J'ai utilisé le module Attributs de menu que vous avez suggéré et attribué des ID uniques aux éléments de menu spécifiques, puis j'ai utilisé jQuery pour injecter le HTML directement là où je le souhaitais. Merci pour les conseils. +1
Lester Peabody
"Vous pouvez facilement placer le bloc du menu personnalisé dans une région souhaitée via l'interface d'administration Drupal" ++. Je trouve cette solution beaucoup plus simple.
cdmo
1

Vous voudrez peut-être examiner le module Nice Menus . Voici une citation à ce sujet (à partir de la page du projet du module):

... active les menus déroulants déroulants / droite / gauche. Il utilise uniquement CSS pour la plupart des navigateurs, avec un minimum de Javascript pour IE6. (La version 2 utilise le plugin Superfish jQuery pour tous les navigateurs, avec une option pour désactiver JS, et retombe en CSS uniquement pour les navigateurs qui peuvent le gérer.)

Trois styles / types de menus sont actuellement possibles: horizontal, menus déroulants; vertical, les menus volent vers la gauche; vertical, les menus volent vers la droite. Il y a une page de manuel qui fournit une liste de sites qui utilisent des menus Nice .

Nice Menus crée des blocs qui peuvent être associés à n'importe quel menu de site existant et qui peuvent être placés partout où des blocs normaux peuvent être placés dans un thème. Pour les thématiques, il est également possible de thématiser un menu en tant que Nice Menu directement en utilisant les fonctions de thème fournies afin qu'un bloc ne soit pas nécessaire. Une fonction de thème spécifique pour le menu Liens principaux est disponible. Les fonctions de thème permettent également à un développeur de passer dans une arborescence de menu personnalisée de leur création (c'est-à-dire sans utiliser un menu Drupal.) Il y a plus d'informations sur la façon d'utiliser les fonctions de thème dans la documentation .

Le module est livré avec un jeu de couleurs générique simple qui peut être entièrement remplacé soit en ajoutant le CSS de remplacement à la feuille de style normale du thème ou en créant un fichier CSS Nice Menus et en disant à Nice Menus de l'utiliser plutôt que son propre fichier par défaut via le global configuration du thème. Plusieurs exemples de substitution CSS sont fournis dans le fichier README.txt inclus et dans le manuel .

Stan Ascher
la source
Je ne vois pas pourquoi quelqu'un a rejeté cette réponse. Avec Nice Menus, vous pouvez cibler un élément de menu individuel car il a sa propre classe. Ensuite, vous pouvez utiliser un graphique comme arrière-plan pour cette classe individuelle. Je l'ai déjà fait sur quelques projets majeurs.
Stan Ascher
2
Je n'ai pas voté contre, mais je dirai que cela ne répond pas au cœur de la ou des questions que j'ai posées, à savoir comment creuser dans le cœur du thème Drupal pour les éléments de menu. C'est pourquoi ces questions ne reçoivent jamais de réponse complète, car il y a toujours un module que le nom de quelqu'un laisse tomber. Je me fiche des modules, je veux faire du codage de modèle.
Lester Peabody
1
Je n'ai pas non plus voté contre, mais je veux ajouter à ce que Lester a dit. Lorsque vous proposez un module dans votre réponse, vous devez également expliquer pourquoi vous le proposez et comment il peut être utilisé pour résoudre le problème du PO. Sans ces détails, votre réponse peut être considérée comme peu utile et potentiellement rejetée. J'ai fait cette erreur sur mes premières réponses ici aussi.
sheena_d
0

Selon ce que vous souhaitez personnaliser, votre approche est très complexe. Habituellement, je crée le menu via l'interface Drupal comme vous l'avez suggéré. Je prends le module développeur de thème et Firebug pour découvrir quels modèles, crochets et directives CSS je dois écraser pour l'adapter à mes besoins.

Il vaut la peine d'envisager de créer un sous-thème du thème de base que vous utilisez avant de commencer à peaufiner. Cela facilite la mise à jour de votre thème de base.

BetaRide
la source
J'ai besoin d'injecter du HTML personnalisé dans les éléments <li> des éléments de menu. Plus précisément, j'ajoute des icônes Twitter Bootstrap.
Lester Peabody
0

voici un code intelligent qui peut accéder à tous les éléments de menu pour tout niveau 2 ou 3 ou plus

placez ce code dans votre fichier tpl n'oubliez pas d'appeler boostrap js et css dernières versions:

<!-- menu -->  

        <?php 

          # get menu with all levels 
          menu_tree_all_data('main-menu');
          $menu = menu_build_tree('main-menu');


          # help function for listing submenus for each link     
          function sub_menu_links($var){
           $submenu ='<ul class="dropdown-menu">';

              foreach ($var as $sub) {

                $path = str_replace("<front>",'' ,$sub["link"]["link_path"]);

                 if(count($sub["below"]) > 0 ){
                      $submenu .= '<li class="dropdown-submenu" ><a href="javascript:void(0);" >'.$sub["link"]["link_title"].'</a>';
                      $submenu .=  sub_menu_links($sub["below"]);
                      $submenu .= '</li>'; 
                  }else{
                      $submenu .= '<li><a href="'.$path.'">'.$sub["link"]["link_title"].'</a>'; 
                      $submenu .= '</li>'; 
                   }

              }
            $submenu .= ' </ul>';

            return $submenu;

          }


          # help function for more than 2 levels
          function menu_links($menu){

             $links = '<ul class="nav navbar-nav">';
             foreach ($menu as $link) {

              if(count($link["below"]) > 0 ){ 

                $path = str_replace("<front>",'' ,$link["link"]["link_path"]);

                $links .=  '<li class="dropdown ">';
                $links .= '<a href="javascript:void(0);" class="dropdown-toggle" data-toggle="dropdown">'.$link["link"]["link_title"].'</a>';
                      /* print "<pre>";
                      var_dump( $link["below"]);
                       print "</pre>";*/
                $links .= sub_menu_links($link["below"]); 


                $links .= '</li>' ;

              }else{
                  $links .= '<li>';
                  $links .= '<a href="'.$path.'">'.$link["link"]["link_title"].'</a>'; 
                  $links .= '</li>' ;
              }



              } 
              $links .= '</ul>';
              return  $links ;
          } 


          print menu_links($menu);


           ?>

ce code renverra le menu pour les classes css vous pouvez utiliser votre propre j'utilise bootstrap avec des css personnalisés

ce code est après un travail acharné il peut vous faire gagner du temps et il est testé sur drupal 7.x et fonctionne très bien pour le menu principal, vous pouvez changer le menu comme vous le souhaitez

elaz
la source