既読チェック機能付きの検索機能を追加する方法

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

はじめに

サイト内検索を行い、表示された投稿一覧から気になった記事を確認する際、通常の操作では、確認した記事を把握しづらかったり、検索結果から記事を開く操作を繰り返したりする必要があります。

そこで、記事の確認作業を効率化するため、検索結果からの記事閲覧に「既読チェック」と「固定ウィンドウでのプレビュー」を組み合わせた仕組みを導入します。

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

目的

サイト内検索の結果一覧から複数の記事を確認する際、デフォルトの操作では主に2つの課題があります。

  1. ページ遷移やタブの連続作成で確認作業の手間が増える
    通常の左クリックでは検索結果から直接ページ移動してしまうため、元の結果一覧へ戻る手間が発生します。
    また、右クリックで「新しいタブで開く」を繰り返すとブラウザのタブが大量に増え、閲覧のテンポが損なわれます。
  1. どの記事まで確認したかを一目で判別できない
    複数の記事を順番にチェックしていると、既に内容を確認した記事と未確認の記事の区別がつかなくなり、確認作業の抜け漏れや重複が発生しやすくなります。

今回紹介するコードを導入することで、これらの課題を解決できます。
リンクをクリックするだけで、チェックボックスと背景色が自動で変化して「既読」が一目で分かります。
さらに、記事は常に同じ1つのサブウィンドウ(タブ)で開くため、タブを散らかさずテンポよく確認できます。

完成イメージ

使用方法

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

[my_search]

実装手順

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

// ショートコードを追加
add_shortcode('my_search', function () {
  ob_start();
  ?>
  <div class="search" data-ajax-url="<?php echo esc_url(admin_url('admin-ajax.php')); ?>" data-nonce="<?php echo esc_attr(wp_create_nonce('search_action')); ?>">
    <!-- 検索フォーム -->
    <form class="search-box input-box search-form" role="search">
      <input type="text" class="search__keyword" placeholder="サイト内を検索" aria-label="サイト内を検索">
      <button type="submit" class="search-submit search__btn" aria-label="検索">
        <span class="fas fa-search" aria-hidden="true"></span>
      </button>
    </form>

    <!-- 検索結果リスト -->
    <ul class="search__results"></ul>
  </div>
  <?php
  return ob_get_clean();
});


/**
 * 検索結果を表示するためのAjax処理
 *
 * @return void
 */
if (!function_exists('search_ajax')) :
function search_ajax() {
  // nonceチェック
  check_ajax_referer('search_action', 'search_nonce');

  // 検索キーワード取得
  $keyword = isset($_POST['keyword'])
    ? sanitize_text_field(wp_unslash($_POST['keyword']))
    : '';

  if ($keyword === '') {
    wp_die();
  }

  // 記事検索(全件取得)
  $query = new WP_Query([
    'post_type'      => 'post',
    'post_status'    => 'publish',
    'posts_per_page' => -1,
    's'              => $keyword,
    'no_found_rows'  => false,
  ]);

  if (!$query->have_posts()) {
    echo '<li>記事が見つかりませんでした。</li>';
  } else {
    while ($query->have_posts()) {
      $query->the_post();
      ?>
      <li data-post-id="<?php echo esc_attr(get_the_ID()); ?>">
        <input type="checkbox" class="search__item-check" disabled>
        <a href="<?php echo esc_url(get_permalink()); ?>" target="fixed_preview_window"><?php echo esc_html(get_the_title()); ?></a>
      </li>
      <?php
    }
  }

  wp_reset_postdata();
  wp_die();
}
endif;


// Ajaxアクションを追加
add_action('wp_ajax_search', 'search_ajax');
add_action('wp_ajax_nopriv_search', 'search_ajax');


// フロント用JS・CSSを追加
add_action('wp_enqueue_scripts', function () {
  ob_start();
  ?>
  .search {
    margin-bottom: 20px;

    .search__results {
      display: flex;
      flex-direction: column;
      gap: 4px;
      list-style: none;
      margin-top: 1em;
      max-height: 400px;
      overflow-y: auto;
      padding: 0;

      li {
        align-items: center;
        border-radius: 4px;
        display: flex;
        font-size: 13px;
        gap: 8px;
        padding: 2px 8px;

        input[type="checkbox"] {
          accent-color: #0073aa;
        }

        a {
          color: #333;
          text-decoration: none;
          word-break: break-all;
        }

        &.is-checked {
          background-color: #eef2f7;
        }
      }
    }
  }
  <?php

  $handle = 'search-checked';

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

  ob_start();
  ?>
  jQuery(function ($) {
    // 検索イベント
    $(".search").on("submit", ".search-form", function (e) {
      e.preventDefault();

      const $box = $(this).closest(".search");
      const $results = $box.find(".search__results");
      const keyword = $box.find(".search__keyword").val().trim();

      if (!keyword) {
        $results.empty();
        return;
      }

      $results.html("<li>検索中...</li>");

      $.post($box.data("ajax-url"), {
        action: "search",
        search_nonce: $box.data("nonce"),
        keyword: keyword
      })
        .done((html) => $results.html(html))
        .fail(() => $results.html("<li>通信エラーが発生しました。</li>"));
    });

    // 記事クリックイベント
    $(".search").on("click", ".search__results a", function () {
      $(this)
        .closest("li")
        .addClass("is-checked")
        .find(".search__item-check")
        .prop("checked", true);
    });
  });
  <?php
  wp_add_inline_script('jquery', ob_get_clean());
});

さいごに

今回紹介した方法を使えば、サイト内検索で複数のタブを開き直したり、検索画面に戻ったりする手間を大幅に削減できます。
気になった記事を固定ウィンドウでテンポよく確認しつつ、チェックボックスで既読状態も一目で把握できるため、リサーチや過去記事のチェック効率が劇的に向上します。

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