見出し画像

WordPressの「Smart Custom Fields」プラグインに入力補完機能をつけてみた

私が運営しているMr.Childrenのドラム機材まとめサイト「ジェン通」では、セットリスト記事の投稿の際に「Smart Custom Fields」プラグインを利用して演奏曲と機材を入力・管理しています。

「ジェン通」では保存された曲名と機材名をリンクさせることで
・この楽曲で使用されたことのある機材
・この機材を使って演奏されたことのある楽曲
を相互に表示しているのですが、その性質上表記ミスが発生すると上手く機能しないためデータ入力の正確性が求められます。

過去に入力したデータをサジェストしてくれる入力補完機能があれば楽なのにな…と思っていたのですが標準ではそのような機能はないため、JavaScriptのautocomplete機能を利用して実現しました。

※WordPressプラグインを直接修正することになりますので、初心者にはおすすめ出来ません。WordPressやphpのエラーが出た場合に自分で解析して対応出来ることが望ましいです。

1.「functions.php」の設定

WordPressのfunctions.phpにautocompleteで入力候補として表示するリストを取得する関数を記述します。

#入力補完用関数
function ajax_get_labels(){
	// jsから受け渡しするデータ
	$searchKey = $_POST['searchKey'];
	$returnObj = array();
	
	//jsから受け取ったデータをキーにデータを検索
	//ここから
	global $wpdb; 
	$query = "SELECT DISTINCT meta_value FROM postmeta WHERE meta_key = 'equipment' AND meta_value LIKE '%".$searchKey."%'";
	$result_list = $wpdb->get_results($wpdb->prepare($query,$value1_id,ARRAY_A));
	
	foreach($result_list as $result){
		$returnObj[] = $result->meta_value;
	}
	//ここまではjsonで返す応答を変数に配列で格納できれば実装方法は問いません

	// json形式に出力
	echo json_encode( $returnObj );
	die();
}
add_action( 'wp_ajax_ajax_get_labels', 'ajax_get_labels' );
add_action( 'wp_ajax_nopriv_ajax_get_labels', 'ajax_get_labels' );

このサンプルでは動的な結果を返すためDB問い合わせを実施していますが、候補リストを格納する変数「$returnObj」に候補を入れる方法はお好みでどうぞ。

2.「editor.js」の追記

「Smart Custom Fields」プラグイン本体の中にある「editor.js」を修正します。(ファイルパス:smart-custom-fields/js/editor.js)

場所はどこでも良いので、jQuery( function( $ ) {}内に以下のautocompleteの初期化/破棄を行う関数を定義します。「Smart Custom Fields」で作成されるinputフィールドには「widefat」というClass名が付与されるので、そのフィールドを対象にautocompleteが効くようにします。

//autocomplete初期化
function autocomplete_init() {
	var autoCompleteClass = wrapper.find('.widefat')
	autoCompleteClass.autocomplete({
		source: function (request, response) {
			$.ajax({
				type: 'POST',
				//WordPressの管理画面ならajaxurlの変数名でAjax用のadmin-ajax.phpがリダイレクトされるようになっているはず
				url: ajaxurl,
				dataType: 'json',
				data: {
					// データ受け渡し
					'searchKey' : request.term,
					// actionにはfunction.phpで作成した関数名を指定
					'action' : 'ajax_get_labels'
				}
			}).done(function (res) {
				response(res);
			}).fail(function (res) {
				console.error(res.responseJSON);
				response([]);
			});
		},
		delay: 300,
		minLength: 1
	});
}

//autocomplete破棄
function autocomplete_disable(){
	var autoCompleteClass = wrapper.find('.widefat')
	autoCompleteClass.autocomplete("destroy");
}

以下のタイミングでautocompleteが初期化されるようにします。
・「editor.js」が読み込まれカスタムフィールドの編集画面が表示された時
・グループが追加され入力フィールドが増える時
グループが増える時はただ初期化するだけでなく、破棄→初期化という処理が必要になりますのでグループ追加の関数の前後に初期化と破棄の関数を配置します。

$( '.smart-cf-meta-box' ).each( function( i, e ) {
	(中略)

	//要素読み込み時にautocompleteを初期化
	autocomplete_init();

	/**
	* グループ追加ボタン
	*/
	btn_add_repeat_group.click( function( e ) {
		(中略)
		//グループ要素追加前にautocompleteの定義を破棄
		autocomplete_disable();
		add_repeat_group( $( this ) );
		//グループ要素追加後にautocompleteを初期化し再定義
		autocomplete_init();
	} );

以上の修正で上手くサジェストが効くようになりました。

カスタムフィールド入力欄での入力補完の様子

「Smart Custom Fields」はWordPressの公式ディレクトリに掲載されているプラグインのため、改変自由のはずなので自己流でカスタマイズしてみました。今まであまりJavaScriptは本格的に触ってこなかったので基本的なことから調べつつ苦労しましたが、最終的にわずか2箇所の修正で実現出来たので気持ち良かったです。

というかそもそもの「Smart Custom Fields」自体が痒いところに手が届きまくる素晴らしいプラグインであり、ソースコードも読みやすかったのが大きかったと言えます。いつも本当にお世話になっています。

とはいえシンプルな改変で済んだように見えるのはWordPressの管理画面がデフォルトで沢山のJavaScriptソースを読み込んでいるお陰なので、例えば一般に公開するようなページの中で同じことを実現しようとすると途端にハードルが上がりますのでご注意下さい。私は先にそっちで検証を初めて依存性のエラーが出まくって酷い目に合いました。


この記事が気に入ったらサポートをしてみませんか?