ブロックエディターのタグ入力にタグクラウド機能を追加した

説明

ブロックエディターのタグ入力には「よく使われているタグから選択」から表示される「タグクラウド」がない。ブロックエディターの不満なところのひとつがこれであり、うまく解消することができないか考えてみた。

タグクラウド機能を追加したイメージ

はじめに、ブロックエディターの編集画面にあるサイドバーの基本部分は「パネル」で構成されており、タグ入力フォーム部分についてはとりあえず「投稿タグパネル」と呼ぶことにする。今回クラウド機能を追加するイメージは次の通りである。

「投稿タグパネル」のビフォア・アフター

「新規タグを追加」ラベルの後にアイコンを追加し、そのアイコンをクリックすることで「タグクラウド」部分が表示・非表示を切り替える仕組みとなる。

「タグクラウド」の内容はAJAXで

今回の対応はプラグインの形をとる。PHP部分は次の通りだ。

$token_field_enhance = new token_field_enhance();

class token_field_enhance {
	public function __construct() {
		add_action( 'admin_enqueue_scripts', array( &$this, 'admin_enqueue_scripts' ) );
		add_action( 'wp_ajax_get_tagcloud', 'wp_ajax_get_tagcloud' );
	}
	public function admin_enqueue_scripts() {
		global $pagenow;
		if ( in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) ) {
			wp_enqueue_script(
				'token-field-enhance',
				plugins_url( 'assets/js/enhance.js', __FILE__ ),
				array( 'wp-blocks' ),
				true
			);
		}
	}
}

まずadmin_enqueue_scriptsアクションを使ってタグクラウドを追加するためのJavaScriptファイルを設定。その次にwp_ajax_get_tagcloudアクションを使ってAJAX経由でタグクラウドの表示内容をやり取りできるようにしている。ここで指定されたwp_ajax_get_tagcloud関数は/wp-admin/includes/ajax-actions.phpで定義されており、このPHPファイルはAJAXリクエスト時に自動的に読み込まれるため、自身で用意する必要はない。

JavaScriptファイルの内容はブロックエディターの仕組みにより次のようになった。

( function($) {
	$(window).on( 'load', function() {
		$( '.components-button' ).click( function () {
			var components_panel = $(this).parents( 'div' );
			if ( components_panel.attr( 'class' ) == 'components-panel__body' ) {
				setTimeout( extend_tagcloud, 500 );
			}
		} );
		$( '.edit-post-sidebar__panel-tab' ).click( function () {
			setTimeout( extend_tagcloud, 500 );
		} );
		extend_tagcloud(); setTimeout( extend_tagcloud, 500 );
	} );

	function extend_tagcloud() {
		$( '.components-form-token-field__label' ).each( function () {
			$.post( ajaxurl, { action: 'get_tagcloud', tax: 'post_tag' },
				function( response ) {
					var tagcloud_style = 'margin-top: 10px; border: solid 1px #ddd; padding: 10px 5px 5px 5px;';
					$( '.components-form-token-field__input-container' )
						.after( '<div id="tagcloud-post_tag" class="the-tagcloud hidden" style="' + tagcloud_style + '">' + response + '</div>' );
					var input = $( '#' + $( 'label.components-form-token-field__label' ).attr( 'for' ) );
					$( '.tag-cloud-link' ).click( function () {
						var new_token = $(this).text();
						$( '.components-form-token-field__token span[aria-hidden=true]' ).each( function () {
							if ( $(this).text() == new_token ) { new_token = null; }
						} );
						if ( new_token != null ) {
							input.focus().attr( 'size', new_token.length + 1 ).val( new_token );
						}
					} );
				}
			);
			$(this).after( ' <span class="dashicons dashicons-tagcloud toggle-tagcloud">&nbsp;</span>' );
			$( '.toggle-tagcloud' ).click( function () {
				$( '#tagcloud-post_tag' ).toggleClass( 'hidden' );
			} );
		} );
	}
} )( jQuery );

※バージョン5.0.3でloadイベント時にcomponents-form-token-field__labelクラスを取得できなくなったので調整しました。

1つ目のポイントはwindow.onloadイベントを使用しているところ。これはdocument.onreadyイベントのタイミングではブロックエディターのパネル部分がまだ作成されていないことが理由である。

onloadイベントの処理では、サイドバーの「文書」タブがクリックされた場合とパネルのタイトル部分(ボタン)がクリックされた場合と初回に「タグクラウド」を追加する処理を行っている。このような処理の理由としては、まずパネルのタイトル部分をクリックするとその内容の表示・非表示を切り替えできるようになっているが、どうやら表示の際に内容をその都度作り直しており、タグクラウドの部分もそのタイミングで追加する必要があるためだ。また「文書」タブをクリックした場合にも同じような振る舞いになっており、こちらでも同じ処理が必要となる。この部分については「投稿タグパネル」の内容を作り直したタイミングで何等かのアクションが実行されていればそのアクションを登録する実現できる。JavaScriptでもPHPと同じようなアクションやフィルターの仕組みが実装されているが、今回はその情報を見つけるに至らなかったため、このような実装とした。

実際にタグクラウドを追加するextend_tagcloud関数では「新規タグを追加」ラベルの有無を調べ、ラベルが存在する場合のみ、AJAXでタグクラウドの内容を取得して追加している。

タグクラウドのリンクをクリックして実際にタグを追加する部分に関しては力およばず暫定対応となる。タグの入力ボックスは「投稿タグパネル」の内容を作り直すごとにid属性が変わる。このため「新規タグを追加」ラベルのfor属性値からidを割り出し、そのvalue値を更新するようにした。

さて標準のタグ入力ボックスではタグとなるワードを入力して「Enter」か「,」をキーを押すことでタグとして確定される。今回の対応ではタグクラウド内のリンクをクリックすることでタグ入力ボックスにその内容は表示されるが、続いて「Enter」か「,」キーを押しても何も起こらない。新しいタグとして確定させるためには、続けてスペースキーを押し、その後で「Enter」か「,」をキーを押す必要がある。このような力業を使わないスマートな解決方法があることに期待したい。


最終更新 : 2019年01月10日 11:07


お勧め

wp_set_script_translations(2019年2月26日 更新)

bool wp_set_script_translations( string $handle [ , string $domain = 'default' [ , string $path = null ] ] )
JavaScript向け翻訳ファイル情報を設定する。

wp_sanitize_redirect(2012年4月25日 更新)

string wp_sanitize_redirect( string $locaution )
URLの文字列をサニタイズする。

wp_set_post_categories(2012年7月5日 更新)

mixed wp_set_post_categories( [ int $post_ID = 0 [ , array $post_categories = array() ] ] )
投稿情報にカテゴリーを設定する。

wp_get_attachment_link(2018年5月27日 更新)

string wp_get_attachment_link( [ int $id = 0 [ , mixed $size = 'thumbnail' [ , bool $permalink = false [ , bool $icon = false [ , mixed $text = false ] ] ] ] ] )
添付ファイルへのリンクを示すHTMLテキストを取得する。

get_post_ancestors(2014年12月26日 更新)

array get_post_ancestors( mixed $post )
先祖の投稿IDを取得する。