web-dev-qa-db-fra.com

Ajouter du HTML personnalisé au dernier élément du sous-menu

J'ajoute un menu personnalisé à mon thème wordpress. J'ai besoin d'ajouter du code HTML personnalisé à l'élément final du sous-menu - avant la fermeture du sous-menu principal </ul>

J'ai enregistré mon nouveau menu

//functions.php
function register_my_menus() {
register_nav_menus(
array(
  'accessories'  => __( 'Accessories Menu' )
)
);
}

et j'ai appelé mon nouveau menu dans mon en-tête

//header.php
wp_nav_menu( array( 'theme_location' => 'accessories', 
                    'walker'   => BENZ_Walker_Nav_Menu_ACC                 
        ) ); 

J'ai essayé de modifier un nouveau Walker pour ajouter cette div à mon sous-menu, mais cela a ajouté la div pour chaque élément de menu

// functions.php ==this adds one div foreach li==comment out
class BENZ_Walker_Nav_Menu_ACC extends Walker_Nav_Menu {

function start_lvl(&$output, $depth) {
    $output .= '<ul class="sub-menu">';
}
  function end_lvl(&$output, $depth) {
        //$output .='<div>the div that I want to show only once</div></ul>';
        $output .= '</ul>';
        }
    }       
}

Encore une fois, l'exemple ci-dessus est commenté car il ne fonctionne pas pour mes besoins

J'ai aussi essayé d'ajouter un peu de HTML à la fin du menu avec les deux exemples suivants ...

//functions.php == this shows custom html after the top-level `<li>`
function BENZ_menu_extras($menu, $args) {
if( 'accessories' !== $args->theme_location )
    return $menu;
return $menu . '<div>the div that I want to show only once</div>';
}
add_filter('wp_nav_menu_items','BENZ_menu_extras', 10, 2);

c'est très proche, cependant je n'ai pas besoin du HTML dans la hiérarchie supérieure du menu, mais d'un niveau plus profond.

J'ai aussi essayé cet exemple ..

function add_last_nav_item($items, $args) {
if (!is_admin() && $args->theme_location == 'accessories') {
$items .= '<div>the div that I want to show only once</div>';
}
return $items;
}
add_filter( 'wp_nav_menu_items', 'add_last_nav_item', 10, 2 );

cependant, cela fait la même chose que le premier exemple listé ...

Comment utiliser l'une des fonctions ci-dessus avec la variable $depth pour ajouter mon div ici ....

<div class="accessories menu">
  <ul id="menu-accessories" class="menu sf-menu">
    <li id="menu-item-1905">
      <a class="sf-with-ul" href="http://#">ACCESSORIES</a>
      <ul class="sub-menu">
        <li id="menu-item-1897">
          <a class="sf-with-ul" href="http://#">stuff</a>
          <ul class="sub-menu">
            <li id="menu-item-1899">stuff1</li>
            <li id="menu-item-1898">stuff1</li>
          </ul>
        </li>
        <li id="menu-item-1903">
          <a class="sf-with-ul" href="http://#">other stuff</a>
          <ul class="sub-menu">
            <li id="menu-item-1906">other stuff1</li>
            <li id="menu-item-1907">other stuff2</li>
          </ul>
        </li>
        <li id="menu-item-1911">
          <a class="sf-with-ul" href="http://#">blue stuff</a>
          <ul class="sub-menu">
            <li id="menu-item-1912">blue stuff 1</li>
            <li id="menu-item-1913">blut stuff 2</li>
          </ul>
        </li>
    <!--This is where i want to put one div so its in the main submenu-->
    <div>the div that I want to show only once</div>
      </ul>
    </li>
  </ul>
</div>

https://jsfiddle.net/qpbpofpp/3/

Merci d'avoir lu.

--BEGIN EDIT-- C'est le plus proche que j'ai eu ..

 //functions.php
 class BENZ_Walker_Nav_Menu_ACC extends Walker_Nav_Menu {
 function start_lvl(&$output, $depth) {
       $output .= '<ul class="sub-menu">';
}
function end_lvl(&$output, $depth) {
    if ($depth = 2){
        $output .= '<div>the div that I want to show only once</div></ul>';
    } else {
        $output .= '</ul>';
           }
    }    
}

sauf pour le moment montre après les trois sous-menus, j'ai juste besoin de montrer une fois

5
RobBenz

Ok, il s’avère que par défaut, $depth dans la fonction end_lvl() commence à 0 s’il s’agit d’un sous-menu et s’incrémente à mesure que la profondeur augmente. Nous devons donc tester si {$depth} est égal à 0 pour l'appliquer uniquement au premier ensemble de sous-menus:

function end_lvl( &$output, $depth, $args ) {
    if( 0 == $depth ) {
        $output .= '<div>the div that I want to show only once</div>';
    }

    $indent = str_repeat( "\t", $depth );
    $output .= "{$indent}</ul>\n";
}
5
Howdy_McGee

Le filtre sur wp_nav_menu_items devrait être le moyen de le faire. Exécutez ce qui suit (il suffit de pirater temporairement le thème header.php:

function add_last_nav_item($items, $args) {
  // if (!is_admin() && $args->theme_location == 'accessories') {
    $items .= '<div>the div that I want to show only once</div>';
  // }
  return $items;
}
add_filter( 'wp_nav_menu_items', 'add_last_nav_item', 10, 2 );

wp_nav_menu();

Vous devriez voir exactement l'effet que vous décrivez. Si vous voyez ce code sortir à tous les niveaux, il y a probablement un problème avec votre lecteur personnalisé. Si vous regardez la source , vous verrez que dans Core ce filtre est appliqué une fois après que l’arborescence du menu ait été "parcourue". Il ne devrait pas être d'ajouter plus d'un élément à la fin des éléments déjà existants pour le menu.

Pour contrôler le niveau d'affichage de votre code, un marcheur modifié serait la meilleure approche:

class BENZ_Walker_Nav_Menu_ACC extends Walker_Nav_Menu {
  private $insert = true;
  function start_lvl(&$output, $depth) {
    $output .= '<ul class="sub-menu">';
  }
  function end_lvl(&$output, $depth) {
    if ($depth = 2 && $this->insert === true){
      $output .= '<div>the div that I want to show only once</div></ul>';
      $this->insert = false;
    } else {
      $output .= '</ul>';
    }
  }    
}

wp_nav_menu(array('walker' => new BENZ_Walker_Nav_Menu_ACC));

Notez la propriété de la classe $insert. Défini sur false lors de la première insertion, assurez-vous qu'il ne s'affiche qu'une fois.

4
s_ha_dum