「MW WP FORM」を使用していると、datepickerのカスタマイズを依頼される時が稀にあります。
特に、日付や曜日を選択できないようにカスタマイズしないと業務に支障が出る場合には必須となるでしょう。
この記事では、「MW WP FORM」の日付・曜日の非選択化を説明していきます。
# この記事で解決すること
- MW WP FORMのdatepickerとACFなどのカスタムフィールドを組み合わせて、「休みの曜日などの定休日」や「祝日」を設定し、選択できないようにする。
- また、営業期間が限られている業種の場合、例えば10月1日~12月2日までしか選択できないようにできる。
- datepickerの「休みの曜日」や「祝日」が管理画面から変更できる
前提
前提として、datepickerはjQueryのプラグインなので、php+js(jQuery)にて処理をしていきます。
実装方法を多少なりとも理解していただきたいので、フルコードは最後に記載します。
また、下記の作業は完了しているものとします。
- 「MW WP FORM」でのdatepickerの設定
- ACFなどのカスタムフィールドが実装できる環境(defaultでもいいかも…)
処理の順序
- 管理画面
- 「MW WP FORM」でのdatepickerの設定見直し(必須ではない)
- ACFでフィールド設定
- phpの処理
- 処理をどこで行うかの決定
- 日付取得の関数化(フォーマット)
- 営業期間の処理(日付選択範囲の設定)
- 定休日の処理(曜日)
- 定休日の処理(日付)
- js(jQuery)の処理
- 営業期間の設定
- 定休日の処理(日付)
- 定休日の処理(曜日)
- 実装
管理画面
「MW WP FORM」の設定見直し
この項は必須ではありませんが、MW WP FORMのdatepickerの仕様の理解として説明しておきます。
まず、私の場合は下記に設定しました。
MWWPFORM内エディタ
[mwform_datepicker name="カレンダー" size="30" js="dateFormat:'yy年Md日',firstDay:1"]
特に確認してほしいのが、jsの部分です。
この部分ではdatepickerの設定を記載しています。
name | remark |
---|---|
dateFormat | 日付のフォーマット |
firstDay | 0: 日曜日始まり 1: 月曜日始まり |
その他の詳しい仕様は下記URLのオプションタブで詳しく説明してくれています。
ちなみに、この部分で期間指定しようとしたのですが動きませんでした。
ACFでフィールド設定
次にACFでのフィールド設定です。
ACFをインストールすると管理画面のメニューの下の方に「カスタムフィールド」の項目が表示されますので、そちらの「新規追加」から新たにフィールドグループを追加してください。
次にフィールド追加から、「営業開始日」「営業終了日」「定休日(曜日)」「定休日(日付)」を下記の内容に設定します。(サンプルなのでお好きなように)
営業開始日
項目名 | 設定値 |
---|---|
フィールドラベル | 営業開始日 |
フィールド名 | range_start |
フィールドタイプ | デイトピッカー |
表示フォーマット | 任意 |
返り値のフォーマット | Custom: Y/n/j |
週の始まり | 任意 |
営業終了日
項目名 | 設定値 |
---|---|
フィールドラベル | 営業終了日 |
フィールド名 | range_end |
フィールドタイプ | デイトピッカー |
表示フォーマット | 任意 |
返り値のフォーマット | Custom: Y/n/j |
週の始まり | 任意 |
定休日(曜日)
項目名 | 設定値 |
---|---|
フィールドラベル | 定休日(曜日) |
フィールド名 | holiday_date |
フィールドタイプ | チェックボックス |
選択肢 | 1 : 月 2 : 火 3 : 水 4 : 木 5 : 金 6 : 土 0 : 日 |
レイアウト | 水平(の方が見やすいです) |
返り値 | Value |
定休日(日付)
日付はdatepickerの繰り返しフィールドでもいいのですが、繰り返しフィールドがPro版の機能なので、今回はテキストエリアにて説明します。
項目名 | 設置値 |
---|---|
フィールドラベル | 定休日(日付) |
フィールド名 | holiday_day |
フィールドタイプ | テキストエリア |
説明 | 形式(半角英数):2022-01-01 ※改行で複数入力 ※文字列の最後にスペースが入らないよう気をつける (って書いておいた方がトラブル少ないです) |
改行 | 何もしない |
位置
また、フィールドの下に別ブロックで「位置」という項目がありますが、これはこのフィールドを表示させる箇所を指定するものとなります。
今回は仮に「ページ」「等しい」「予約」としましょう。
※「予約」はこちらで設定しているフォームを設置したページのページ名ですので、任意のページを指定してください。
尚、今回設定した「予約」のslugは「reserve」とします。
ここまでで管理画面内の設定は完了となります。
phpの処理
処理をどこで行うかの決定
さて、php側の処理ですが、、、
どこでしましょうか。。。
思いつく選択肢は3つです。
functions.php
orcustom_functions.php
に入れ込む
jsが絡んでいるので、処理がかなり面倒
日付を更新できなくていい場合は、jsだけなのでwp_enqueue_scripts
で対処できます- ページテンプレート(
page-slug.php
)を作って入れ込む
私はこの方法で入れていますが、そもそもページテンプレートを作成していない人口の方が多そう footer.php
に入れ込む
よしこれだ!
※まとめたコードは最後に記載しますので、読んでいただけると嬉しいです!
日付取得の関数化(フォーマット)
今回はACFの返り値とは異なる日付フォーマットを多用しますので、わかりやすいように関数化しておきましょう。
function returnDate($date) {
// $date = "Y/n/j"
$array = explode('/', $date);
// "Y,n-1,j"
return "{$array[0]},{$array[1]}-1,{$array[2]}";
}
ACFで設定した値が「Y/n/j」なので、explode
を使用して「/」で分割し、配列にしています。
{$array[1]}
を-1しているのは、phpの仕様上です。
営業期間の処理(日付選択範囲の設定)
次に、上記の関数を元に営業期間(営業開始日と営業終了日)を変数に格納します。
// reserve = 位置設定で指定したページのslug
$start_text = returnDate(get_field('range_start', get_page_by_path("reserve")->ID));
$end_text = returnDate(get_field('range_end', get_page_by_path("reserve")->ID));
get_field('フィールド名', ID)
は、「ID」のページにある「フィールド名」の情報を取得してきます。
今回はページIDを入れ込むのが面倒なので、get_page_by_path
で
定休日の処理(曜日)
定休日はjs側に値を送る必要があるので、処理しやすいようにjson形式にパースしておきます。
// 定休日(曜日)の取得
$holiday_date = get_field('holiday_date', get_page_by_path("reserve")->ID);
// 返り値がString型なのでint型に変更
foreach($holiday_date as $k => $v) {
$holiday_date[$k] = (int) $v;
}
// json形式にエンコード
$holiday_date_object = json_encode($holiday_date);
定休日の処理(日付)
こちらもjs側に値を送る必要があるので、処理しやすいようにjson形式にパースしておきます。
// 定休日(日付)の取得
$holiday_day = get_field('holiday_day', get_page_by_path("reserve")->ID);
// 改行で分割して配列に(ACFテキストエリアの性質上)
$holiday_day_array = explode("\r\n", $holiday_day);
// json形式にエンコード
$holiday_day_object = json_encode($holiday_day_array);
ACF内で改行で日付を登録してもらったのは、\r\n
つまり改行で区切って配列化するためです。
ここまででphp側の処理は完了です。
js(jQuery)の処理
今までの処理はあくまで下準備なので、上記を行ったからといって反映されるわけではありません。
ここからはjs(jQuery)を使用して、今まで行った作業が無駄にならないように実装していきます。
営業期間の設定
jQuery(function($) {
$('input[name="カレンダー"]').datepicker('option', 'minDate', new Date(<?php echo $start_text?>));
$('input[name="カレンダー"]').datepicker('option', 'maxDate', new Date(<?php echo $end_text?>));
datepickerのoptionにminDateとmaxDateを送るというコードです。
"カレンダー"
は最初にMW WP FORM内にて設定したname属性になります。
[mwform_datepicker name="カレンダー" size="30" js="dateFormat:'yy年Md日',firstDay:1"]
ちなみにoptionをObjectにしても動くんじゃないかと思いましたが無理でした…
定休日の処理(日付)
$('input[name="カレンダー"]').datepicker('option', 'beforeShowDay', function(date){
// 定休日(曜日)の取得
var holiday_day = <?php echo $holiday_day_object ?>;
// 定休日(曜日)のjsonを回す
for (var i = 0; i < holiday_day.length; i++) {
// 協定世界時のミリ秒取得
var holiday_time = Date.parse(holiday_day[i]);
// 日付を初期化
var holiday = new Date();
// 経過ミリ秒の取得
holiday.setTime(holiday_time);
// 各日付ブロックとの相違判定
if (holiday.getYear() == date.getYear() && holiday.getMonth() == date.getMonth() && holiday.getDate() == date.getDate()) {
return false; // 全て一致で非選択の日付ブロックとする
}
}
簡単に説明すると、「holiday_date
に格納された日付と、カレンダーの日付ブロックが一致すればfalse
(非選択)」という意味です。
定休日の処理(曜日)
// 定休日(曜日)の取得
var holiday_date = <?php echo $holiday_date_object ?>;
// 曜日が一致すれば非選択とする
return [!holiday_date.includes(date.getDay())];
});
});
holidate.date
に各日付ブロックの曜日が含まれていればfalse
(非選択)を返してくれます。
注意しないといけないのは、datepickerの仕様上、false
ではなく[false]
を返さなければいけないということです。
実装
変数に格納できる部分は格納しているので、上述の内容よりもスッキリしていると思います。
変更する箇所は1行目と4行目、35行目です。
footer.php
<?php if(is_page('位置設定で指定したページのslug')):
// 初期設定
$form_page_id = get_page_by_path("位置設定で指定したページのslug")->ID;
// 日付取得の関数化(フォーマット)
function returnDate($date) {
$array = explode('/', $date);
return "{$array[0]},{$array[1]}-1,{$array[2]}";
}
// 営業期間の処理(日付選択範囲の設定)
$start_text = returnDate(get_field('range_start', $form_page_id));
$end_text = returnDate(get_field('range_end', $form_page_id));
// 定休日(曜日)の設定
$holiday_date = get_field('holiday_date', $form_page_id);
foreach($holiday_date as $k => $v) {
$holiday_date[$k] = (int) $v;
}
$holiday_date_object = json_encode($holiday_date);
// 定休日の処理(日付)
$holiday_day = get_field('holiday_day', $form_page_id);
$holiday_day_array = explode("\r\n", $holiday_day);
$holiday_day_object = json_encode($holiday_day_array);
?>
<script>
jQuery(function($) {
// 営業期間の設定
// 複数項目がある場合は $('input[name="カレンダー1"]', 'input[name="カレンダー2"]')
var calendar = $('input[name="カレンダー"]');
calendar.datepicker('option', 'minDate', new Date(<?php echo $start_text?>));
calendar.datepicker('option', 'maxDate', new Date(<?php echo $end_text?>));
// 定休日の処理(日付)
calendar.datepicker('option', 'beforeShowDay', function(date){
var holiday_day = <?php echo $holiday_day_object ?>;
for (var i = 0; i < holiday_day.length; i++) {
var holiday_time = Date.parse(holiday_day[i]);
var holiday = new Date();
holiday.setTime(holiday_time);
if (holiday.getYear() == date.getYear() && holiday.getMonth() == date.getMonth() && holiday.getDate() == date.getDate()) {
return false;
}
}
// 定休日の処理(曜日)
var holiday_date = <?php echo $holiday_date_object ?>;
return [!holiday_date.includes(date.getDay())];
});
});
</script>
<?php endif; ?>
最後に
上記は基本latestのみの確認になるので、絶滅したIEはもちろん、古めのブラウザでは確認していません。
ただ36行目、37行目をはじめ所々参考にできるところはあるのかなと思い記事にしました。
みなさんもぜひ案件に沿ってカスタマイズしてみてください!