プラグインなしで「メガメニュー」を追加する方法

Cocoonカスタマイズ集
この記事は約7分で読めます。
記事内に広告が含まれています。

はじめに

メガメニューとは、通常のドロップダウンメニューよりも大きな領域を使い、多層的なナビゲーションを提供するメニューのことです。

プラグイン「Max Mega Menu」などを使わずに、メガメニューを追加します。
外観→メニューの各メニュー項目に「メガメニューパターンID」を追加し、その内容をメニューとして展開します。

この記事では、この方法について説明します。

完成イメージ

メニュー
メガメニュー

実装手順

以下のコードをfunctions.phpに追加します。

/**
 * メガメニューの対象項目を取得
 *
 * @return array メニュー項目IDをキー、パターンIDを値とする連想配列
 */
if (!function_exists('get_mega_menu_items')):
function get_mega_menu_items() {
  static $mega_map = null;

  // キャッシュを取得
  if ($mega_map !== null) {
    return $mega_map;
  }

  // ナビゲーションメニューIDを取得
  $mega_map  = [];
  $locations = get_nav_menu_locations();
  $menu_id   = isset($locations[NAV_MENU_HEADER]) ? $locations[NAV_MENU_HEADER] : 0;

  if (!$menu_id) {
    return $mega_map;
  }

  // メニュー項目を取得
  $menu_items = wp_get_nav_menu_items($menu_id);

  if (!$menu_items) {
    return $mega_map;
  }

  foreach ($menu_items as $item) {
    // パターンIDを取得
    $pattern_id = absint(get_post_meta($item->ID, 'my_mega_menu_pattern', true));

    if ($pattern_id) {
      // メガメニューを登録
      $mega_map[$item->ID] = $pattern_id;
    }
  }

  return $mega_map;
}
endif;


// メニュー項目に入力フォームを追加
add_filter('wp_nav_menu_item_custom_fields', function ($item_id, $item) {
  // 保存済みのパターンIDを取得
  $pattern_id = get_post_meta($item_id, 'my_mega_menu_pattern', true);

  ?>
  <p class="description description-wide">
    <label for="edit-menu-item-mega-pattern-<?= esc_attr($item_id); ?>">
      メガメニューパターンID<br>
      <input type="number" id="edit-menu-item-mega-pattern-<?= esc_attr($item_id); ?>" name="menu-item-mega-pattern[<?= esc_attr($item_id); ?>]" value="<?= esc_attr($pattern_id); ?>">
    </label>
  </p>
  <?php
}, 10, 2);


// メニュー項目を保存
add_action('wp_update_nav_menu_item', function ($menu_id, $menu_item_id) {
  if (!isset($_POST['menu-item-mega-pattern'][$menu_item_id])) {
    return;
  }

  $pattern_id = absint($_POST['menu-item-mega-pattern'][$menu_item_id]);

  if ($pattern_id > 0) {
    update_post_meta($menu_item_id, 'my_mega_menu_pattern', $pattern_id);
  } else {
    delete_post_meta($menu_item_id, 'my_mega_menu_pattern');
  }
}, 10, 2);


// テンプレート(グローバルナビメニュー)の後ろに追加
add_action('cocoon_part_after__tmp/navi', function () {
  $mega_items = get_mega_menu_items();

  if (empty($mega_items)) {
    return;
  }

  foreach ($mega_items as $item_id => $pattern_id) {
    ?>
    <div class="mega-menu__content" data-menu-item-id="<?= esc_attr($item_id); ?>">
      <?= do_shortcode('[pattern id="' . esc_attr($pattern_id) . '"]'); ?>
    </div>
    <?php
  }
});


// フロント用JS・CSSを追加
add_action('wp_enqueue_scripts', function () {
  $mega_items = get_mega_menu_items();

  if (empty($mega_items)) {
    return;
  }

  ob_start();
  ?>
  .mega-menu__content {
    background-color: #fff;
    display: none;
    left: 0;
    position: absolute;
    width: 100%;
    z-index: 999;
  }
  <?php

  $handle = 'mega-menu';

  wp_register_style($handle, false);
  wp_enqueue_style($handle);
  wp_add_inline_style($handle, ob_get_clean());

  $mega_ids_json = wp_json_encode(array_keys($mega_items));

  ob_start();
  ?>
  jQuery(function ($) {
    const megaIDs = <?= $mega_ids_json; ?>;

    megaIDs.forEach(function (id) {
      const trigger = $('#menu-item-' + id);
      const target  = $('.mega-menu__content[data-menu-item-id="' + id + '"]');

      if (!target.length) {
        return;
      }

      let hideTimer;

      trigger.add(target).hover(
        function () {
          clearTimeout(hideTimer);
          target.stop(true, true).fadeIn(200);
        },
        function () {
          hideTimer = setTimeout(function () {
            target.stop(true, true).fadeOut(200);
          }, 50);
        }
      );
    });
  });
  <?php
  wp_add_inline_script('jquery', ob_get_clean(), 'after');
});

さいごに

今回紹介した方法を使えば、プラグインを使わずに、シンプルにメガメニューを実装できます。
サイトのデザインや使い勝手を向上させたい場合は、ぜひカスタマイズしてみてください。

タイトルとURLをコピーしました