Contact Form 7にSlect2を導入したいのだけど…フォームのidがコロコロ変わってしまうので、とても苦労しました。
jQueryプラグイン「Select2」は、セレクトボックス内の検索機能がついている。プルダウンメニュー、まあいわゆるフォームに使うセレクトボックスの利便性が確実に向上するのだが、プラグインもないし、Contact Form 7のアドオンもないのでWordPressでの導入のハードルは高い。けっきょくコードを書くしかない。
とりあえず人気のメールフォームプラグイン「Contact Form 7」で実装を試した…というお話し。
事の発端は、不動産会社で扱っている物件を投稿で表示しているサイトがあると思ってね…でもって物件ページには問い合わせフォームがあるワケです。物件ページから問い合わせフォームに遷移すると、もちろん不動産物件名が「お問い合わせ物件」の欄に自動的に入るんです。そんな、ゲットでポストなんて、Contact Form 7やElementorのフォームを使えば簡単にできるんです。
でもね…そのクライアントから不吉な言葉が出てきました…投稿にない物件も問い合わせフォームの「お問い合わせ物件」に入れたいんだよねって。その物件はCSVで、どっかにアップロードしておいて、そのCSVを使ってセレクトボックスをつくってよって軽口をたたくわけです。
エッそれってどうするの?投稿のタイトルとCSVを合体してプルダウンを作るってコト?それともCSVファイルには投稿された不動産物件はCSVに直書きされてるの?どっちかしら?と矢継ぎ早に質問すると「基本はCSVでセレクトボックス作って。投稿の物件名とCSVの整合性は、こちらでやるので」とのこと。
よかった。自分がやるのはとりあえずCSVを読み込んで、Contact Form 7上にSelect2でセレクトボックスをつくって、もしポストの値があった場合は、その値をセレクトボックス内で選択状態にすること…というのが判明。
こうして記述してみると意外と大変そう…ってやっぱ大変でした!Contact Form 7でのSelect2の導入は!!
とりあえず仕様を書き起こしてみる
どのような前提条件があるか書き出してみる。
- セレクトボックスを生成するのは、Contact Form 7のアクションフックを使う。
- Contact Form 7はidが切り替わるので固定するようにショードコードで設定する。
- Select2はCDNを参照して利用する。
- Select2の入力欄ではフリーワードを許容する。
- CSVファイルの文字コードはShift-JIS(Excelで作成前提)。
- CSVファイルはフォームのページにカスタムフィールドで設置。
- カスタムフィールド名は「csvfile」。戻り値は「ファイルURL」。
- フォームに遷移する場合は、URLに投稿タイトルを追加して遷移させる(ポストする)。
- ポストをゲットしてページタイトル値がある場合はセレクトボックス内でセレクトの状態にしておく。
- 投稿タイトルをポストする変数名は「pname」。
Contact Form 7側の設定を記述する
Contact Form 7ではフォームに下記の内容を設定する。
5行目の「eventselect」がアクションフックの動作に利用されている。
6行目がSelect2の設定が入っている…。ここで、CDNからのCSSとJavaScriptの読み込みを実行。
-
[eventselect* pname]
-
[text* contact-name]
-
[email* your-email]
-
[textarea* your-message]
[submit "送信"]
そして、ここが重要!6~7行目にかけて1行のJavaScriptが記述されている。
Select2では、セレクトボックスのclassに「select」を割り当てる必要があるのだが、Contact Form 7ではそんな設定ができない(というかできないよう…自信ないけど)。
※下記はdiv内の最初のulタグの最初のliタグのclassを追加する内容。Select2を使う場所により、変わるので、適時、ブラウザのデベロッパーモードで調べて対応してください。
なので、このフォームにはidで明示的に「contact-form-0001」に設定をして、querySelectorを使ってセレクトボックス部分にclassの「select」を割り当てている。
フォームのショードコードを設定する場合は下記のようにidを固定する必要がある。
[contact-form-7 id="###" title="問い合わせフォーム" html_id="contact-form-0001"]
functions.phpにアクションフック記述する
次にContact Form 7のアクションフックを設定する。
4行目はプルダウンメニューを作成するための配列の生成する関数の名称になっている。
こちらはfunctions.phpに追加をする。
function theme_wpcf7_add_form_tag_eventselect() {
wpcf7_add_form_tag( array( 'eventselect', 'eventselect*' ),
'theme_wpcf7_eventselect_form_tag_handler',
array(
'name-attr' => true,
'selectable-values' => true,
)
);
}
add_action( 'wpcf7_init', 'theme_wpcf7_add_form_tag_eventselect', 10, 0 );
functions.phpにセレクトボックスための配列を生成するコードを記述する
下記は、Contact Form 7にセレクトボックス用の配列を生成して戻すコード。
本体ページのAdvanced Custom Fields、カスタムフィールドのCSVファイルを読み込んで、それを配列に格納、URLに物件名がポストされていたら、該当の行を選択済みにしておくという流れ。
function theme_wpcf7_eventselect_form_tag_handler( $tag ) {
// 初期設定 CSVを読み込む配列を定義
$pChartArySJIS = array(); // 物件名格納用配列 Shift-JIS
$pChartAryUTF8 = array(); // 物件名格納用配列 UTF-8
// 物件一覧作成用のCSVのURLを取得
$fileCsvUrl = get_field( 'csvfile' );
// ファイルパスは絶対URLにして読み込む
$filePath = substr( $fileCsvUrl, ( strlen( $fileCsvUrl ) - strpos( $fileCsvUrl, 'cms') ) * -1 );
// 物件一覧CSVファイル存在チェック
$response = @file_get_contents( $filePath );
if( $response !== false ){
//ファイルがあった場合 ファイルを読み込んでUTF8に変換する
$pChartArySJIS = file( $filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ); // 改行を無視 | 空行を無視
$pChartAryUTF8 = mb_convert_encoding( $pChartArySJIS, 'utf-8', 'sjis' ); // 文字コード変換
if ( $pChartAryUTF8 ) {
// オブジェクトのパラメータ値を初期化
$tag->raw_values = array();
$tag->values = array();
$tag->labels = array();
//プルダウンの1行目の文字列「※物件名を入力:物件名の一部の文字で物件が検索できます。」をセットする
array_push( $tag->raw_values, esc_html( '' ) );
array_push( $tag->values, esc_html( '' ) );
array_push( $tag->labels, esc_html( '※物件名を入力:物件名の一部の文字で物件が検索できます。' ) );
// プルダウン用の配列に物件一覧配列の値を格納する
foreach( $pChartAryUTF8 as $val ) {
array_push( $tag->raw_values, esc_html( $val ) );
array_push( $tag->values, esc_html( $val ) );
array_push( $tag->labels, esc_html( $val ) );
}
// URLに値があった場合はプルダウンで選択済みにする処理
// $_GET['pname']がUndefined か調べて処理をする
if ( !empty( $_GET['pname'] ) ) {
$programName = $_GET['pname']; // URLのpnameのパラメータを取得
$programName = mb_convert_encoding( $programName, 'sjis', 'utf-8' );
$programName = mb_convert_encoding( $programName, 'utf-8', 'sjis' );
for( $i = 0 ; $i < count( $pChartAryUTF8 ) ; ++$i ) {
if( strcasecmp( $programName, $pChartAryUTF8[$i] ) == 0 ){
$tag->options = array( 'default:'.(string)($i+2) );
break;
}
}
}
}
}else{
echo '※CSVファイルがありません。';
return;
}
return wpcf7_select_form_tag_handler( $tag );
}
このコードもfunctions.phpに追加をする。
フォームを表示してみると該当部がセレクトボックスに、かつ入力文字列で検索ができるようになっている…ハズ…。