Tematización de menú avanzada en Drupal 7

15

He navegado por la web y no es del todo obvio cómo crear menús personalizados. He buscado durante horas y no he encontrado una sola publicación que ilustre el proceso, de principio a fin, de crear un menú y personalizar su salida. Parece que este es un proceso de varias etapas:

  1. Cree el menú a través de la interfaz de Drupal.
  2. Cree una función de tema en su template.phparchivo para crear un tema de salida
  3. Exponga este menú a un archivo de plantilla (de alguna manera) agregándolo como una variable.
  4. Llame a la themefunción en el menú en el archivo de plantilla.

1 es bastante fácil de hacer, los problemas que encuentro son con 2, 3 y 4. Al mirar la plantilla de página predeterminada, veo que expone el menú principal en la variable $main_menu. Más adelante, en la página, puede ver la función theme('links__system_main_menu', array('links' => $main_menu..., lo que significa que está buscando una función de tema con un nombre apropiado en alguna parte y la está utilizando para generar el resultado.

Sé que si coloco function theme_links__system_main_menu(&$variables) {...}en mi archivo template.php Drupal utilizará esa función en lugar de function theme_menu_links(&$variables) {...}.

Lo que no sé es cómo Drupal vincula el menú personalizado que creé con esa función. Digamos, por ejemplo, que creé un menú llamado My Menu. ¿Podría crear la siguiente función en mi template.phparchivo y tema la salida para ese menú?function theme_links__system_my_menu(&$variables) {...}

Además, ¿cómo se hace que ese menú personalizado esté disponible para un archivo de plantilla? ¿Cómo expone Drupal la $main_menuvariable a page.tpl.php?

Creo que la clave que me falta aquí es cómo incrustar la variable que representa mi menú personalizado en una página de plantilla. En su mayor parte, aunque estoy completamente perdido con qué hacer después de haber creado el menú.

Gracias por la ayuda.

EDITAR: Probablemente debería publicar lo que estoy haciendo. Según mi comentario a BetaRide a continuación, necesito inyectar HTML personalizado en los <li>elementos de los elementos del menú. Específicamente, estoy agregando íconos de Twitter Bootstrap.

Lester Peabody
fuente

Respuestas:

13

La implementación de menús de Drupal es un poco especial, no siempre funciona como parece.

Puede echar un vistazo a la implementación principal de template_preprocess_page () para ver cómo se agregan los enlaces del menú principal como una variable a la plantilla de página. Debe profundizar un poco en los documentos de la API, pero la función que desea llamar en su implementación de theme_preprocess_page () es menu_navigation_links () , que devolverá una matriz de enlaces en el menú.

Mirando la línea 106 del archivo page.tpl.php del núcleo de Drupal , puede ver cómo se relacionan los enlaces del menú principal en la plantilla llamando a la función theme ( ) con un enlace de 'links__system_main_menu'.

Teóricamente, esta implementación debería poder duplicarse con un menú personalizado siguiendo las convenciones de nomenclatura estándar. Entonces, en template.php, podrías tener:

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
}

y en page.tpl.php, agregarías algo como esto:

<?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'))); ?>

Sin embargo, no es necesario agregar el menú personalizado como variable en su plantilla de página. Puede colocar fácilmente el bloque del menú personalizado en una región deseada a través de la interfaz de administración de Drupal. Además, puede cambiar la configuración del sitio para la fuente del menú principal , reemplazando efectivamente la variable predeterminada $ main_menu en page.tpl.php con su menú personalizado.

EDITAR: Acabo de ver su adición sobre su objetivo final de agregar solo algunos html personalizados a los elementos del menú para los iconos. Dependiendo de cómo esté agregando estos íconos, hay un par de opciones diferentes del módulo Drupal.

Iconos de menú : le permite cargar una imagen a través de la configuración del elemento de menú y genera automáticamente CSS (personalizable a través de una plantilla) que agrega la imagen como fondo en el elemento de menú.

Atributos del menú : le permite agregar una clase personalizada a cada elemento del menú a través de su configuración en el administrador. Una vez que se agrega una clase única a cada elemento del menú, puede usar CSS para agregar un icono al elemento del menú o usar JavaScript para inyectar el HTML adicional en el elemento del menú.

sheena_d
fuente
Esto parece responder a todas mis preguntas perfectamente. Esta es una respuesta genial. Probaré esto de inmediato.
Lester Peabody
1
Funcionó, pero tomé en serio la opinión unánime de todos y no utilicé este método. Usé el módulo de Atributos del menú que sugirió y asigné ID únicos a los elementos específicos del menú, y luego usé jQuery para inyectar el HTML directamente donde lo necesitaba. Gracias por los consejos. +1
Lester Peabody
"Puede colocar fácilmente el bloque del menú personalizado en una región deseada a través de la interfaz de administración de Drupal" ++. Creo que esta solución es mucho más simple.
cdmo
1

Es posible que desee consultar el módulo de Menús agradables . Aquí hay una cita al respecto (de la página del proyecto del módulo):

... habilita menús desplegables desplegables / derecha / izquierda. Utiliza solo CSS para la mayoría de los navegadores, con Javascript mínimo para IE6. (La versión 2 usa el complemento Superfish jQuery para todos los navegadores, con una opción para deshabilitar JS, y recurre a CSS solo para los navegadores que pueden manejarlo).

Actualmente son posibles tres estilos / tipos de menús: horizontal, menús desplegables; vertical, los menús vuelan a la izquierda; vertical, los menús vuelan a la derecha. Hay una página de manual que proporciona una lista de sitios que usan menús de Niza .

Nice Menus crea bloques que pueden estar asociados con cualquier menú de sitio existente que se puede colocar donde sea que se puedan colocar bloques normales en un tema. Para los temáticos, también es posible crear un tema como un menú de Niza directamente usando las funciones de tema proporcionadas, por lo que no es necesario un bloque. Está disponible una función de tema específico para el menú Enlaces principales. Las funciones de tema también permiten que un desarrollador pase un árbol de menú personalizado de su creación (es decir, no usa un menú de Drupal). Hay más información sobre cómo usar las funciones de tema en la documentación .

El módulo viene con un esquema de color genérico simple que se puede anular por completo, ya sea agregando el CSS de anulación a la hoja de estilo normal del tema o creando un archivo CSS de Nice Menus y diciéndole a Nice Menus que lo use en lugar de su propio valor predeterminado a través del global configuración del tema Se proporcionan varios ejemplos de anulación de CSS en el archivo README.txt incluido y en el manual .

Stan Ascher
fuente
No veo por qué alguien rechazó esta respuesta. Con Nice Menus, puede apuntar a un elemento de menú individual ya que tiene su propia clase. Luego puede usar un gráfico como fondo para esa clase individual. Lo he hecho antes en un par de proyectos importantes.
Stan Ascher
2
No lo rechacé, pero diré que esto no aborda el núcleo de la (s) pregunta (s) que hice, que es cómo profundizar en el núcleo de la temática de Drupal para los elementos del menú. Es por eso que estas preguntas nunca se responden completamente, porque siempre hay algún módulo que el nombre de alguien deja caer. No me importan los módulos, quiero codificar plantillas.
Lester Peabody
1
Yo tampoco rechacé la votación, pero quiero agregar a lo que dijo Lester. Cuando sugiera un módulo en su respuesta, también debe explicar por qué lo sugiere y cómo se puede usar para resolver el problema del OP. Sin esos detalles, su respuesta puede verse como poco útil y potencialmente rechazada. También cometí ese error en mis primeras respuestas aquí.
sheena_d
0

Dependiendo de lo que desee personalizar, su enfoque es muy difícil. Por lo general, creo el menú a través de la interfaz de Drupal como usted sugirió. Luego tomo el módulo de desarrollador de temas y Firebug para descubrir qué plantillas, ganchos y directivas CSS tengo que sobrescribir para ajustarlo a mis necesidades.

Vale la pena considerar crear un subtema del tema base que está utilizando antes de comenzar a ajustar. Esto hace que sea mucho más fácil actualizar su tema base.

BetaRide
fuente
Necesito inyectar HTML personalizado en los elementos <li> de los elementos del menú. Específicamente, estoy agregando iconos de Twitter Bootstrap.
Lester Peabody
0

Aquí hay un código inteligente que puede acceder a todos los elementos del menú para cualquier nivel 2 o 3 o más

coloque este código dentro de su archivo tpl, no olvide llamar a las últimas versiones de boostrap js y css:

<!-- 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);


           ?>

este código devolverá el menú para las clases de CSS. Puede usar el suyo. Estoy usando Bootstrap con algunos CSS personalizados.

Este código es después de un arduo trabajo, puede ahorrarle tiempo y está probado en drupal 7.xy funciona bien para el menú principal, puede cambiar el menú a su gusto

elaz
fuente