Flatpickrを申込フォームに実装

Wordpressのお申込みフォームでカレンダー機能を実装したのでメモします。
## やりたいこと
* フォームはカレンダー形式で入力
* お申し込みは希望日の3日前まで（申込後3日まで選択不可）
* 日、祝日も選択不可
* 臨時休業日を任意で選択不可に追加できる

何か良いライブラリはないものかと探していたところ「Flatpickr」がイイ感じだったので使ってみました。
jQuery UIの選択肢もありましたが、コードをみたら何かイマイチな感じ。
サポートも終わりだそうで。
スッキリした書き方とデザインも良かったし、軽いということで決めました。

CDNではなくダウンロードしてローカル環境で使用です。

## インストールと準備
下記サイトよりダウンロードしました。
https://flatpickr.js.org/plugins/

サンプルで作ったフォームにjsとcssを組み込みます。
デザインも色々用意されてましたが、どんなものにも合いそうなlightテーマを選択。
ファイルパスはdatepickerディレクトリ作って、全部放り込みました。

```index.html
<!-- headにcss挿入 -->
<link rel="stylesheet" href="./datepicker/flatpickr/dist/flatpickr.min.css">
<link rel="stylesheet" href="./datepicker/flatpickr/dist/themes/light.css">

<!-- /bodyの閉じタグ直前にjs挿入 jQuery使ってます -->
<script src="./datepicker/jquery-3.3.1.min.js"></script>
<script src="./datepicker/flatpickr/dist/flatpickr.min.js"></script>
<!-- 日本語化のファイル -->
<script src="./datepicker/flatpickr/dist/l10n/ja.js"></script>
<!-- myカスタマイズ用 -->
<script src="./datepicker/main.js"></script>
```


まずは日本語化と日曜日始まりにセッティング。
```main.js
$(function () {
    // 日曜日始まり
    flatpickr.l10ns.ja.firstDayOfWeek = 0;
    //inputタグにid="myDate"
    flatpickr('#myDate', {
        //日本語化
        locale: 'ja'
    });
});
```


サンプルはこんな感じです。
![スクリーンショット 2023-09-18 17.29.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641189/0cbb82f2-ef13-26e3-d789-5d4b586c6135.png)
[DEMOサイト →](https://spica.okamechan.com/form-sample/)
※確認画面までで、送信ファイルは外しました。DEMOサイトはWPでなくHTMLです。


## 実装

まずは、お申し込み希望日の3日前までと日曜日は選択不可に。
```main.js
flatpickr('#myDate', {
        //日本語化
        locale: 'ja',
        minDate: new Date().fp_incr(3), //今日より三日後から選択可
        disable: [
          function (date) {
            return date.getDay() === 0; //日曜だけ選択不可
          }
     ],
 });

//disable:は選択不可
//enable:は選択可能

//曜日を追加したい場合||で条件増やします
date.getDay() === 1 || //月曜日
date.getDay() === 2 || //火曜日
date.getDay() === 3 || //水曜日
date.getDay() === 4 || //木曜日
date.getDay() === 5 || //金曜日
date.getDay() === 6 //土曜日
```

### 祝日追加

日本の祝日は毎年変動するので、jsonあたりで何処か配布していないかなと探したところ以下のサイトがわかりやすかったので、使わせてもらいました。
https://holidays-jp.github.io/

過去1年、今年、来年と3年分読み込めます。
過去は要らないけど、来年まであれば十分です。


デジタル庁のサイトも見たけどCSVしかなかった気がする・・・
```main.js
$.ajax({
    // 祝日json読み込み開始
    type: 'GET',
    url: 'https://holidays-jp.github.io/api/v1/date.json',
    dataType: 'json',
  }).then(
    function (json) {
    //祝日の配列を作る
    let holidays = [];
    //日付だけ取得、祝日の説明要らない
      let moji = Object.keys(json);
      holidays.push(moji);
      // 日曜日始まり
      flatpickr.l10ns.ja.firstDayOfWeek = 0;
flatpickr('#myDate', {
        //日本語化
        locale: 'ja',
        minDate: new Date().fp_incr(3), //今日より三日後から選択可
        disable: [
          function (date) {
            return date.getDay() === 0; //日曜だけ選択不可
          },
        //祝日配列を追加
          ...holidays[0],
      });
    },
    function () {
      // 読み込み失敗時の処理
      console.log('読み込みに失敗しました');
    }
  );
});
```

jsonの中身を見てみると日付と祝日の説明が対になってました。
```date.json
{
    "2022-01-01": "元日",
    "2022-01-10": "成人の日",
    "2022-02-11": "建国記念の日",
    "2022-02-23": "天皇誕生日",
    "//": "...以降省略"
}
```
必要なのは日付だけなので、keyを取得。
`Object.keys(json)`
なんか入れ子になってたので、holidays[0]に。


### 任意の日付を追加

夏休みや年末年始、臨時休業の日付も欲しいので、そういった特別な休みも配列として作ります。
以下サンプルとして2023/10/30、 2024/1/17、2024/2/15を追加するとします。
`　let item = ['2023-10-30', '2024-01-17', '2024-2-15'];　`

配列itemを休日の後に追加します。
`　...holidays[0],...item,`　

完成コード
```main.js
$(function () {
$.ajax({
    // 祝日json読み込み開始
    type: 'GET',
    url: 'https://holidays-jp.github.io/api/v1/date.json',
    dataType: 'json',
  }).then(
    function (json) {
    //祝日の配列を作る
    let holidays = [];
    let moji = Object.keys(json);
    holidays.push(moji);
    // 日曜日始まり
    flatpickr.l10ns.ja.firstDayOfWeek = 0;
    //任意の配列
    let item = ['2023-10-30', '2024-01-17', '2024-2-15'];

    flatpickr('#myDate', {
        //日本語化
        locale: 'ja',
        minDate: new Date().fp_incr(3), //今日より三日後から選択可
        disable: [
          function (date) {
            return date.getDay() === 0; //日曜だけ選択不可
          },
        //祝日と任意日付の配列を追加
          ...holidays[0],...item,
      });
    },
    function () {
      // 読み込み失敗時の処理
      console.log('読み込みに失敗しました');
    }
  );
});
```


## Wordpressのmw wp formのフォームに組み込む

クライアント側で入力できるようカスタムフィールドのデイトピッカー使います。
テキストの手入力にするとフォーマットが統一できず値が取れなくなるので。
Advanced Custom FieldsやSmart Custom Fieldsなどが使いやすいです。

値はテンプレートタグでliタグ書き出し。
htmlにしてからjsで書き出した要素を取得します。
要素自体はcssで非表示にしています。

書き出しフォーマットは統一しておきます。
jsonに合わせてY-m-d。

item配列を入れ替えます。
```main.js
jQuery(function () {
let item = [];
//対象のulにid="noneDay"を付けておく
let num = $('#noneDay').find('li').length;
  for (let i = 0; i < num; i++) {
    item.push($('#noneDay li').eq(i).text());
  }

$.ajax({
    // 祝日json読み込み開始
    type: 'GET',
    url: 'https://holidays-jp.github.io/api/v1/date.json',
    dataType: 'json',
  }).then(
    function (json) {
    //祝日の配列を作る
    let holidays = [];
    let moji = Object.keys(json);
    holidays.push(moji);
    // 日曜日始まり
    flatpickr.l10ns.ja.firstDayOfWeek = 0;

    flatpickr('#myDate', {
        //日本語化
        locale: 'ja',
        minDate: new Date().fp_incr(3), //今日より三日後から選択可
        disable: [
          function (date) {
            return date.getDay() === 0; //日曜だけ選択不可
          },
        //祝日と任意日付の配列を追加
          ...holidays[0],...item,
      });
    },
    function () {
      // 読み込み失敗時の処理
      console.log('読み込みに失敗しました');
    }
  );
});
```
あとはWPのダッシュボードでmw wp formのフォームタグにtype="text"選んでidセレクタを付けます。（date pickerは使わないです）

入力フォームをクリックすると同じようにカレンダーが出てきて日付選択できます。