プラグインなしで「検索サジェスト」機能を追加する方法

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

はじめに

プラグイン「SearchWP Live Ajax Search」などを使わずに、独自のショートコードで「検索サジェスト」機能を追加します。

検索フォームにキーワードを入力すると、関連する投稿タイトルが自動的に表示され、ユーザーはその中から選ぶことができます。
この機能は、投稿に含まれる検索キーワードを元に、最大5件のタイトルを表示します。

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

完成イメージ

使用方法

以下にショートコードを示します。

[my_suggestions]

実装方法

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

// ショートコードを追加
add_shortcode('my_suggestions', function () {
  $action_url = home_url('/');

  ob_start();
  ?>
  <div class="search-suggestions">
    <form class="search-box input-box search-suggestions__form" method="get" action="<?= esc_url($action_url); ?>">
      <input type="text" id="search-input" class="search-edit search-suggestions__input" placeholder="サイト内を検索" name="s" aria-label="input">
      <button type="submit" class="search-submit search-suggestions__submit" aria-label="button"><span class="fas fa-search" aria-hidden="true"></span></button>
    </form>
    <div id="suggestions" class="suggestions-container search-suggestions__list"></div>
  </div>
  <?php
  return ob_get_clean();
});


/**
 * 検索候補の記事タイトルをAjaxで取得
 *
 * @return void
 */
if (!function_exists('get_search_suggestions')):
function get_search_suggestions() {
  $query = isset($_POST['s']) ? sanitize_text_field($_POST['s']) : '';

  // クエリが空の場合は空の配列を返却して終了
  if (empty($query)) {
    wp_send_json([]);
    wp_die();
  }

  $wp_query = new WP_Query([
    'post_type'      => 'post',
    'posts_per_page' => 5,
    's'              => $query,
  ]);

  $suggestions = [];

  while ($wp_query->have_posts()) {
    $wp_query->the_post();

    $suggestions[] = [
      'title' => get_the_title(),
    ];
  }

  wp_reset_postdata();

  wp_send_json($suggestions);
  wp_die();
}
endif;


// Ajaxアクションを追加
add_action('wp_ajax_search_suggestions',        'get_search_suggestions');
add_action('wp_ajax_nopriv_search_suggestions', 'get_search_suggestions');


// フロント用JS・CSSを追加
add_action('wp_enqueue_scripts', function () {
  ob_start();
  ?>
  .search-suggestions__list {
    border: 1px solid #ccc;
    box-shadow: 0 0 3px rgb(0 0 0 / 20%);
    display: none;
    margin-top: 1em;
    padding: 15px;
    position: relative;
  }

  .search-suggestions__list::before {
    background-color: #fff;
    border-left: 1px solid #ccc;
    border-top: 1px solid #ccc;
    content: '';
    display: block;
    height: 16px;
    left: 50%;
    position: absolute;
    top: -4px;
    transform: rotate(45deg) translateX(-50%);
    width: 16px;
  }

  .search-suggestions__item {
    border-bottom: 1px dotted #ccc;
    cursor: pointer;
  }

  .search-suggestions__item:last-child {
    border: 0;
  }
  <?php

  $handle = 'search-suggestions';

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

  $ajax_url = esc_url(admin_url('admin-ajax.php'));

  ob_start();
  ?>
  jQuery(function ($) {
    const searchInput = $('#search-input');
    const suggestions = $('#suggestions');

    // 入力値の変更を監視
    searchInput.on('input', function () {
      const query = searchInput.val().trim();

      // 2文字未満はサジェストを非表示
      if (query.length < 2) {
        suggestions.empty().hide();
        return;
      }

      $.ajax({
        url: '<?= $ajax_url; ?>',
        type: 'POST',
        dataType: 'json',
        data: {
          action: 'search_suggestions',
          s: query
        },
        cache: false,

        success: function (data) {
          suggestions.empty().hide();

          // 検索候補を表示
          if (data.length > 0) {
            suggestions.show();

            data.forEach(function (post) {
              const item = $('<div>')
                .addClass('search-suggestions__item')
                .text(post.title)
                .on('click', function (event) {
                  event.preventDefault();

                  searchInput.val(post.title).focus();
                  suggestions.empty().hide();
                });

              suggestions.append(item);
            });
          }
        },

        error: function () {
          suggestions.empty().hide();
        }
      });
    });


    // フォーム・サジェスト領域外のクリックを確認
    $(document).on('click', function (event) {
      if (
        !searchInput.is(event.target) &&
        !suggestions.is(event.target) &&
        suggestions.has(event.target).length === 0
      ) {
        suggestions.empty().hide();
      }
    });
  });
  <?php
  wp_add_inline_script('jquery', ob_get_clean());
});

さいごに

今回紹介した方法を使えば、WordPressサイトに検索サジェスト機能を簡単に追加できます。
これにより、ユーザーはより快適にサイト内の情報を探すことができ、ユーザー体験の向上が期待できます。

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