年月だけの選択も可能なdatepicker
いままで筆者はjQuery MobileとJTSage DateBoxを利用して、ドラム式で日付や年月の選択のUIを作成していました。
しかし、jQuery MobileがOpenJSにより非推奨となりました。OpenJS Foundationは「主要なJavaScriptおよびWebソリューションと関連テクノロジーの普及と継続的な開発を促進する」ことを目的のひとつとしています。
その財団が8年近く更新のないjQuery Mobileを非推奨と指針を示したのに従い、筆者もその環境をBootstrap5に差し替えることにしました。
それに伴って、今回jQuery Moblieと一緒に非推奨となったjQuery UIに依存しているJTSageのDateBoxの機能の代替を探しました。
2022/12追記
BootstrapやjQueryに依存しないjs-datepickerをカスタマイズして、年月だけの選択を可能にさせたので記事の最後に加えました。
2024/2追記
モダンなブラウザなら、input の type を month にすることで、月単位のピッカーを表示させることができるようです。
bootstrap-datepicker
Bootstrap環境用のDate Pickerを探したところbootstrap-datepickerを見つけました。
求めていたドラム式ではなくカレンダー式のDate Pickerになりますが、設定を変更することでMonth Picker(年月のみの選択)にもできることがわかったのでこれを利用することにしました。
こちらも3年前から更新されていませんが、いいほうにとらえば完成されているということでしょう。また、jQuery本体への依存もあります。jQuery本体は開発が続けられ非推奨とはなっていませんが、BootStap自体がjQueryからの脱却による軽量化を図っていてる中でのjQueryの選択は若干残念です。
Bootstrap
bootstrap-datepickerを利用するためには、BootstrapとjQueryが必要です。
BootstrapはBootstrap ダウンロードページからファイルをダウンロードしてください。 展開したフォルダの中のcssサブフォルダに入っているbootstrap.min.cssと、jsサブフォルダ中のbootstrap.bundle.min.jsを読み込めば利用できます。先の日本語のサイトの方はまだ5.0.0-beta1ですが、https://getbootstrap.com/(英語版?)の方には5.1.3が配布されていたので、筆者はバージョン5.1.3を利用しました。
また、CDNも利用可能です。公式ページではjsDeliverがホストとして紹介されていました。
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha256-YvdLHPgkqJ8DVUxjjnGVlMMJtNimJ6dYkowFFvp4kKs=" crossorigin="anonymous"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha256-cMPWkL3FzjuaFSfEYESYmjF25hCIL6mfRSPnW8OVvM4=" crossorigin="anonymous"></script>
本家のBootstrap5ではその依存がなくなりましたが、bootstrap-datepickerにはjQueryが必要なので読み込みます。
jQueryもサイトからダウンロードするか、CDNを利用してjquery.min.jsを読み込みます。
ちなみにバージョン3.6をBootstrapと合わせて、jsDeliverで使いたい場合は次のアドレスを用います。
bootstrap-datepickerの基本的な使い方
bootstrap-datepickerのダウンロードは、documentにリンクがあるOnline Demoのページから可能です。
Demoのページで、「Download 1.9.0」(バージョンは執筆時点のものです)をクリックしてダウンロードして展開したファイルの中で今回使うのは次の3つです。
- bootstrap-datepicker.min.js
jsフォルダの中にある本体です。
- bootstrap-datepicker3.css
cssフォルダの中にあるcssです。
- bootstrap-datepicker.ja.min.js
localesフォルダにある日本語化ファイルです。
これらもjsDeliverで配布されています。
<script src="https://cdn.jsdelivr.net/npm/bootstrap-datepicker@1.9.0/dist/locales/bootstrap-datepicker.ja.min.js" integrity="sha256-IX182a23hiQE65+kYOND1ZIX2Vpl0cHb96g9nJqqqW0=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap-datepicker@1.9.0/dist/js/bootstrap-datepicker.min.js" integrity="sha256-bqVeqGdJ7h/lYPq6xrPv/YGzMEb6dNxlfiTUHSgRCp8=" crossorigin="anonymous"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-datepicker@1.9.0/dist/css/bootstrap-datepicker3.css" integrity="sha256-AghQEDQh6JXTN1iI/BatwbIHpJRKQcg2lay7DE5U/RQ=" crossorigin="anonymous">
Bootstrap、jQuery、bootstrap-datepickerの環境を整えた状態で次のようにすることで、カレンダー式のDatePickerを設置することができます。
sample.html
...
<input id="datepicker" type="text" />
<script>
$('#datepicker').datepicker();
</script>
...
こうするとテキストボックスをクリックした際に、英語表記のカレンダーが表示され、日付を選ぶとテキストボックスに挿入されます。
これを日本語にするには、$('#datepicker').datepicker()の引数にオブジェクトで設定をあたます。またデフォルトの状態だと、年月の範囲がありません。西暦2099年や3025年といった値も指定できてしまします。なのでstartDateとendDateを使って日付範囲を制限します。日付範囲にはJavaScriptのDateオブジェクトを渡すほか、'-7d'(7日前)といった値で与えることもできます。さらに、デフォルトだとテキストボックスにセットされる値はYYYY/MM/DD形式となりますが、/ではなく-にしたいといったことがあったらformatの値を渡すことで、設定の変更が可能です。
他、オプションは多彩にあるので、先のbootstrap-datepickerのOnline Demoのページや、Documentを確認してみてくさい。
また、日付範囲を制限する際に便利なmoment.jsに代わる日付ライブラリのDay.jsについても、当ブログで紹介していますので、よかったら読んでみてください。
sample2.html
...
$('#sandbox-container input').datepicker({
language: "ja",
startDate: '-5d',
endDate: new Date(),
format: "yyyy-mm-dd"
});
...
ちなみに、bootstrap-datepicker.ja.min.jsでもformatを指定している部分があり、language:jaを指定すると読み込まれますので、こちらでもformatを変えることができます。
bootstrap-datepickerをmonth-pickerに
カレンダーによるdate pickerをmonth pickerにつまり、月までの選択に変えます。
変えますといっても設定を変更するだけです。先に設定するオプションの値に、minViewModeとmaxViewModeを追加します。
この値は0:が日付選択、1:が月選択、2:が年選択となります。なので、最小粒度を1:の月にすることで年月だけを選択することができます。選択した際の値も年月までにするためにformatも変えます。あわせて、年より上の粒度は誤操作の原因となるので制限します。
もし選択した際の年月が年月日のままだったら、bootstrap-datepicker.ja.min.jsのfomartの部分も変更してみてください。
sample3.html
...
$('#sandbox-container input').datepicker({
language: "ja",
format: "yyyy/mm",
minViewMode: 1,
maxViewMode: 2
});
...
z-index
js-datepickerのz-indexはDOM中のz-indexの最大値に10を加えたものになるようですが、筆者の環境でcssにz-indexを指定した要素の後ろ側になってしまうことがありました。その際は、インスタンス作成時に「zIndexOffset」オプションを用いることで、z-indexの値を調整できます。
この値は通常10のオフセットをいくつにするかという値で、例えば100にしたらDOM中のz-indexの最大値に100を加えるという意味になります。
sample4.html
...
$('#sandbox-container input').datepicker({
language: "ja",
format: "yyyy/mm/dd DD",
zIndexOffset: 100
});
...
integrityとcrossorigin(補足)
ちなみにCDN利用時に設定するintegrity属性ですが、これは取得するソースのハッシュでソースの改ざんを検知する為に用いられます。
この値が違っていると次のようなエラーがでます。
もうひとつのcrossorigin属性ですが、これはCORS(オリジン間のソース共有)のリクエストを構成するものです。
未設定や設定エラー時を含めてデフォルト設定は「anonymous」になっていて、異なったオリジンに対しクッキーやSSL証明書等のユーザー情報は送信されません。
この値に「use-credentials」を設定すると異なったCORSのために資格情報を利用します。
稼働サンプル
稼働サンプルを用意しました。Bootstrap用のCSSを読み込むと、このページのCSSが崩れてしまうので別ウインドウで開きます。
jQuery: | - |
Bootstrap(JS): | - |
datepicker(JS): | - |
datepicker-locale: | - |
Bootstrap(CSS): | - |
datepicker(CSS): | - |
ライブラリを読み込んでください
BootstrapやjQueryに依存しないjs-datepicker
先にも書いたようにjQueryへの依存が少し気になっていたので、それを利用していないdatepickerであるjs-datepickerrをカスタマイズして年月だけの選択を可能にさせました。(js-datepickerはBootstrapにも依存していません)
カスタマイズした後のソースコードはgithubで公開しています。
オリジナルのオプション「monthPicker:ture」を設定する事で年月だけの選択に切り替わります。これを設定しなければ通常のjs-datepickerと同様に使えます。
元々の機能である年月の選択機能(overlay)をフックさせて、年月だけのモードの際は指定月の1日を返して終了させているだけのコードです。
またオリジナルはoverlayでは年月をキー入力で受け付けますが、コード上の都合でその機能をやめ矢印での選択制にしています。
こちらのサンプルファイルはgithubのdistフォルダ内にあります。js,css,htmlの3つのファイルを同階層に置いた状態で.htmlを表示させればサンプルが動くと思います。
git経由でコードをcloneする場合の注意ですが、package.jsonはfoke元のままになっています。
オリジナルのpackage.jsonでは npm run build で実行されるコマンドが「NODE_OPTIONS=--openssl-legacy-provider webpack --mode production --env.prod webpack --mode production --env.prod」に設定されています。
これをWindows環境で実行すると
というエラーになります。NODE_OPTIONSはを環境変数として手動でセットすることにして、コマンドをwebpack以降だけにすることで、ビルドができます。