はじめに
以下の質問に回答します。
Cocoonの設定項目は数多く、目的の項目を見つけるのが大変です。
そこで、Cocoon設定画面内でキーワードを検索し、該当するタブを赤色で表示します。
この記事では、この方法について説明します。
完成イメージ

実装手順
以下のコードをfunctions.phpに追加します。
add_action('admin_enqueue_scripts', function ($hook_suffix) {
$page_hook = get_plugin_page_hookname('theme-settings', '');
if ($hook_suffix !== $page_hook) {
return;
}
ob_start();
?>
jQuery(function ($) {
// 検索フォームを追加
$('.admin-settings h1').after('<input type="text" id="hvn-key"><button type="button" id="hvn-button" class="button-primary">検索</button>');
$('#hvn-button').on('click', function () {
const key = $('#hvn-key').val().trim();
// 既存の色をリセット
$('.tab-label').css('background-color', '');
// キーワードが空なら終了
if (!key) {
return;
}
// 各タブを検索
$('[id*="tab"].metabox-holder').each(function () {
const $content = $(this);
const text = $content.text();
// キーワードが見つからなければ次へ
if (text.indexOf(key) === -1) {
return;
}
// content → label に変換して対応するタブを取得
const id = $content.attr('id');
const labelId = '#' + id.replace('content', 'label');
// 該当タブを強調
$(labelId).css('background-color', '#ff0000');
});
});
});
<?php
wp_add_inline_script('jquery', ob_get_clean(), 'after');
}, 999);
拡張:CSS Custom Highlight APIでテキストをハイライト表示する方法
前述のコードでは、文字を装飾するために<span class="highlight">などのタグでHTML構造を書き換える(DOM操作を行う)必要がありました。
しかし、管理画面やフォーム内でDOMを直接書き換えると、レイアウト崩れやイベントの破損、入力データの不具合を引き起こすリスクがあり、本文内のテキストハイライトには対応できませんでした。
今回のコードでは、「CSS Custom Highlight API」を採用により、DOM構造を変更しません。
これにより、管理画面のシステムやフォーム要素に悪影響を与えることなく、安全に本文内のキーワードまでピンポイントでハイライトできるよう改善されています。
完成イメージ

実装手順
以下のコードをfunctions.phpに追加します。
add_action('admin_enqueue_scripts', function ($hook_suffix) {
// 対象ページのフック名を取得
$page_hook = get_plugin_page_hookname('theme-settings', '');
if ($hook_suffix !== $page_hook) {
return;
}
// CSS Custom Highlight APIのスタイルを追加
wp_add_inline_style('wp-admin', '
::highlight(search-result) {
background-color: #ff0000;
color: #ffffff;
}
');
ob_start();
?>
jQuery(function ($) {
// 検索フォームを追加
$('.admin-settings h1').after('<input type="text" id="hvn-key"><button type="button" id="hvn-button" class="button-primary">検索</button>');
// 検索ボタンのクリック処理
$('#hvn-button').on('click', function () {
const key = $('#hvn-key').val().trim();
// 既存のハイライトとタブの選択色を解除
if (typeof CSS !== 'undefined' && CSS.highlights) {
CSS.highlights.delete('search-result');
}
$('.tab-label').css('background-color', '');
// 検索文字列が空なら処理しない
if (!key) {
return;
}
// 各タブの内容を検索
$('[id*="tab"].metabox-holder').each(function () {
const $content = $(this);
const text = $content.text();
// 検索文字列を含むタブを選択状態にする
if (text.indexOf(key) !== -1) {
const id = $content.attr('id');
const labelId = '#' + id.replace('content', 'label');
$(labelId).css('background-color', '#ff0000');
}
});
// #tabs内のテキストを検索してハイライト
if ($('#tabs').length && typeof CSS !== 'undefined' && CSS.highlights) {
const ranges = [];
const lowerKey = key.toLowerCase();
/**
* テキストノードから検索文字列の範囲を取得
*
* @param {Node} node 検索対象のノード
* @return {void}
*/
function findRanges(node) {
if (node.nodeType === Node.TEXT_NODE) {
const nodeText = node.nodeValue;
const lowerNodeText = nodeText.toLowerCase();
let startPos = 0;
let index;
// テキスト内のすべての一致箇所を取得
while ((index = lowerNodeText.indexOf(lowerKey, startPos)) !== -1) {
const range = new Range();
range.setStart(node, index);
range.setEnd(node, index + key.length);
ranges.push(range);
startPos = index + key.length;
}
} else if (node.nodeType === Node.ELEMENT_NODE && node.childNodes) {
// 検索対象外の要素を除外
const tagName = node.tagName.toUpperCase();
if (
tagName !== 'SCRIPT' &&
tagName !== 'STYLE' &&
tagName !== 'TEXTAREA' &&
tagName !== 'INPUT'
) {
// 子要素を再帰的に検索
for (let i = 0; i < node.childNodes.length; i++) {
findRanges(node.childNodes[i]);
}
}
}
}
// #tabs内を検索
findRanges($('#tabs')[0]);
// 検索結果にハイライトを適用
if (ranges.length > 0) {
const searchHighlight = new Highlight(...ranges);
CSS.highlights.set('search-result', searchHighlight);
}
}
});
});
<?php
wp_add_inline_script('jquery', ob_get_clean(), 'after');
}, 999);
さいごに
管理画面内の要素を操作するために、どのようにJavaScriptを実行するかを検討してみました。
ただし、実用性はあまり高くないため、あくまで参考としてご覧ください。

