「AIR DATEPICKER」の使い方 ~基礎編~


どうも。kapyです。
案件で日付を範囲選択できるDatePickerを探していたところ、痒い所に手が届くこの子を見つけたので、ご紹介です。
IE対応しているのも、良き。

###動作確認した環境
Google Chrome 88.0.4324.150 / firefox 81.0.2 / IE 11 / safari 14.0.3 /
 
##概要
###そもそも DatePicker とは
ウェブページ上で、カレンダー風に日付選択できるUIのこと。
基本、javascriptのライブラリを用いることが多い。
各ライブラリの比較などは、[こちら](https://deep-blog.jp/engineer/12578/)が参考になりました。githubの星などは数えてませんが、あしからず。
今回は都合上、日付の範囲選択が出来ることが、第一だったので、掲題に至ります。（細かく見てないだけでもっと優秀なのがあるかもしれないです。）

###AIR DATEPICKERについて
ロシアの方作成のようです。[ドキュメント](http://t1m0n.name/air-datepicker/docs/)が優秀すぎます。勘のいい人、コーディング知識のある人だったら、だいたいわかります。


###ダウンロード
筆者はbowerを使っていなかったので、アナログに[git](https://github.com/t1m0n/air-datepicker/tree/master/dist/js)から直接、持ってきています。cssとjsの二種類あれば、ひとまず大丈夫です。


##AIR DATEPICKERの基本的な使い方
inputもしくは、divなどのブロックエレメントにクラス名を追加するだけで、発火します。
initさせるようなスクリプトをjsで書くことは不要です。
inputの場合は、クリックで開くモーダル仕様、divなどの場合は、初めからDatePickerが開いている状態になります。
（もちろん、jsの方でエレメントを指定して発火、詳細設定を付与することも可能です）

```index.html
<input type="text" class="datepicker-here">
<div class="datepicker-here"></div>
```

or

```index.js
$('#myElement').datepicker({
  //js指定のプロパティは後述します
  props:content
});
```



###data属性で指定するプロパティ
プロパティは、data属性で設定することができます。

`data-position`
[エレメントから見た方向 吹き出し位置]で設定します。間はスペースです。
横から出すときはあまりないかもしれませんが、一応出せるみたいです。
（横から出す時、二つ目のプロパティのtopとbottomが逆な気がする。。。。。紛らわしい。）

```index.html
<!-- inputの上部 真ん中部分に吹き出し -->
<input type="text" class="datepicker-here" data-position='top center'/>
<!-- inputの下部 左部分に吹き出し -->
<input type="text" class="datepicker-here" data-position='bottom left'/>
<!-- inputの左 下部分に吹き出し -->
<input type="text" class="datepicker-here" data-position='top top'/>
```

`data-language`
ライブラリの中の言語や日付表記を書き換えます。初期設定はロシア語なので、どうあがいても筆者はわかりませんでした。
公式が用意してくれている、[こちらのファイル](https://github.com/t1m0n/air-datepicker/tree/master/src/js/i18n)を読み込みつつ、この属性を与えると、発火してくれるようですが、残念ながら日本語のバージョンはありません。適当に作りましょう。

```index.html
<input type="text" class="datepicker-here" data-language="ja" data-position='top　center'/>
```

```datepicker.ja.js
$.fn.datepicker.language['ja'] = {
    days: ['日', '月', '火', '水', '木', '金', '土'],
    daysShort: ['日', '月', '火', '水', '木', '金', '土'],
    daysMin: ['日', '月', '火', '水', '木', '金', '土'],
    months: ['1月','2月','3月','4月','5月','6月', '7月','8月','9月','10月','11月','12月'],
    monthsShort: ['1月','2月','3月','4月','5月','6月', '7月','8月','9月','10月','11月','12月'],
    today: '今日',
    clear: 'クリア',
    dateFormat: 'yyyy-mm-dd',
    timeFormat: 'hh:ii aa',
    firstDay: 0
};
```
注）dateFormat,timeFormatは、inputに出力される値の雛形

 `data-range`
今回、お目当てだったプロパティ
設定するだけで簡単に日付の範囲選択を実現できます。控えめに言ってネ申
`data-multiple-dates-separator`で、区切る値を設定することも可能

```index.html
<input type="text" class="datepicker-here" data-range="true" data-multiple-dates-separator=" - " data-language="ja" data-position='top center'/>
```

 `data-timepicker`
筆者は使いませんでしたが、日付+時刻でも指定できます。
UIをここから別物に代替するには、少し骨が折れそうですが、使い勝手は良さそうです。

```index.html
<input type="text" class="datepicker-here" data-timepicker="true" data-language="ja" data-position='top center'/>
```



###JSで指定するプロパティ
実はJSの方でも、しっかり設定できます。
これまでのデータ属性へ記載したプロパティは、下記の方法でも設定できます。

```index.js
$('#myElement').datepicker({
  position:'top center',
  language:"ja",
  range:true,
  timepicker:true,
});
```

####JSでしか指定不可なプロパティ
data属性では制御できませんが、便利なものがいくつかあります。

`autoClose`
boolean型で、trueの時、値を選択後、自動で閉じてくれます。
初期値はfalse。
日付の範囲選択と合わせると、便利です。

`clearButton`
boolean型で、trueの時、DatePicker下部にクリアボタンを置いてくれます。
初期値はfalse。
ボタンの名前は、言語指定の箇所で設定できます。

`maxDate`or`minDate`
選択可能な日付の範囲を設定できます。型はdate。
指定なしなら、date
例えば、以下のように使えば、今日以降しか選択できない、という状態になります。

```javascript
$('#myElement').datepicker({
  minDate:new Date()//今日以降しか、選べなくする
});
```
初期値は、javascriptのDateObjectに依存していると思われますが、未確認です。
>Date の最大値は、確実な整数の最大値 (Number.MAX_SAFE_INTEGER、9,007,199,254,740,991) と同じ値ではないことに注意が必要です。代わりに ECMA-262 では、 UTC の 1970年1月1日から前後 ±100,000,000 (1億) 日 (つまり、紀元前271821年4月20日 - 紀元275760年9月13日) を標準の Date オブジェクトで表すことができると定義しています。
[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date)


`navTitles`
DatePickerの上部真ん中のタイトルのフォーマットを指定できます。
daysが元々表示される箇所,そこをクリックすると、月、年設定が出てきます。
出てくる範囲は、先述のmaxDate,minDate次第です。

```javascript
$('#myElement').datepicker({
  navTitles : {
    days: 'MM, <i>yyyy</i>',
    months: 'yyyy',
    years: 'yyyy1 - yyyy2'
  }
});
```

####イベント系
それ以外に、イベントごとで処理を追加したいときなどは、js一択です。

`onShow`,`onHide`イベント
その名の通り、DatePickerが表示or非表示になったとき、発火するイベントです。
何もせず、直感的に書くと、イベントが開始と終了で二回、実行されるようなので、一度のみ実行する際は、下記のように扱います。
例には、onShowだけ記載しますが、用法はonHideも同じです。

```index.js
$('#myElement').datepicker({
  onShow:function(dp,animationCompleted){
    //dp -> pluginのinstance。省略不可
    //animationCompleted -> アニメーションの開始、修了フラッグ
    console.log('aaa');//二回実行
    if(!animationCompleted){
      console.log('bbb');
    }
    /*
    result
       >>aaa
       >>bbb
       >>aaa
   */
  }
});
```


`selectDate`
日付が選択された時、つまり、DatePickerのセルをクリックしたときに、発火します。
リアルタイムで値を取得したいときに便利です。というより、changeイベントやonkeyupイベントは発火しません。
諦めてこちらを使いましょう。

```index.js
$('#myElement').datepicker({
  
  onSelect:function(formattedDate, date, inst){
  //formattedDate -> format化したdate string型
  //date -> date型を選択した個数の配列で返す。
  //inst -> pluginのinstance,
});
```

##終わりに
ひとまず、以上です。初投稿なので、わかりづらい部分、多々ある気もします。
コメントいただければ、適宜改訂します。
こういうのを実装したい、などもできるだけ一緒に考えるので、連絡ください。
もし、参考になったよ、というかたがおられましたら、twitterのDMでも、LGTMでも反応いただけると、次回記事のモチベーションになります。

あと余談ですが、筆者はとある案件で、JQueryのコンフリクトを解消できず、jsで制御がうまくいきませんでした。
その時の対応をまとめた[記事](https://qiita.com/kapy/items/d20947b868f2b6b55b6f)も執筆しているので「プラグインが使えない（怒）」となっている方には、多少のご助力が出来るかもしれません。

最後までお付き合いいただき、ありがとうございました。