どうも。kapyです。
先述の基礎編は、前座です。
気持ちとしてはこちらが書きたい内容でした。
「AIR DATEPICKER」はJQuery環境下なので、昔からあるページなどで自前のプラグイン化していると、うまく動きませんました。
そんなときは諦めて、ライブラリを直接編集しましょう。
###動作確認した環境
Google Chrome 88.0.4324.150 / firefox 81.0.2 / IE 11 / safari 14.0.3 /
###AIR DATEPICKERについて
公式ドキュメント
ダウンロード
##何が原因で動かなかったか
軽く、今回なぜライブラリの直接編集に至ったのか、書いておきます。
直接の原因は、よくある$マークのコンフリクトです。
noConflictやJQuery直打ちなど、ググって試しては見たものの、一向に動作する気配がなく、
さらには、animate関数など他の便利な関数達も使えない不便な状況でした。
かと言って、消すと、また別のファイルでが起こってしまい、編集可能な範囲での解決は困難だと、判断しました。
(外部案件だと、よくある。。?)
##そうか。ライブラリに直接書けばいい
###まずは、規約を確認
今回のライブラリは、MITライセンスです。商用ライブラリだと、改変不可の場合もあるようなので、一応注意しておきましょう。
###最低限の保守性
さて、ライブラリの編集に踏み切るとしても、軽量化は、そのままにしておきたい。。。
運用面も考慮し、以下の3点に注意をおきました。
- 一旦、min.jsを整形プラグインで整形しなおして、あとで、改行などをとる
- 後から見た人もわかるよう、ファイル名の変更
- 出来る限り、自前の変数と関数は、他のファイルで参照しておく
####① 一旦、min.jsを整形ライブラリで整形しなおして、あとで、改行などをとる
筆者は整形にvscodeのbeautifyという拡張機能を使っています。
まあ、インデントわけが見れればいいので、chrome開発者ツールなどでも、可能です。
Chromeデベロッパーツールで圧縮(minified)されたJavaScriptを読みやすく表示する
軽量化し直すときは、こちらを使いました。
compress.com
####② 後から見た人もわかるよう、ファイル名の変更
一応、編集してしまっているので、名前を変えて、保存しておきます。
誰かがコピーしようとしても、これは弄くり回してるよ、ということで、今回は「datepicker.min.local.js」とします。
####③ 出来る限り、自前の変数と関数は、他のファイルで参照しておく
最終的に、編集後のライブラリは軽量化しなおして、元に戻しておきたいので、運用上修正が発生しうるところは、別ファイルで管理することにします。
今回は「datepicker.options.js」という名前で管理します。
###実際に書いてみる
今回、手を入れたのは以下です。それぞれ解説します。
- minDate/maxDateを外部変数により制御
- onSelectイベント時に値を取得、外部関数で処理
- onHideイベント時に、データ処理用の関数を忍ばせる
- 閉じるボタンを無理やり追加
- クリック時にスマホだと画面にカレンダーが収まらないので、スクロール関数を付与
###minDate/maxDateを外部変数により制御
今回、日付の選択できる期間を、絞りたかったので、予め用意した変数を差し込みます。
var minDateInput = new Date(2020,10,1)//2020/11/1から
var maxDateInput = new Date(2021,2,31//2021/3/31まで
次に変数をライブラリの初期設定のところにぶち込みます。
ちなみに、clearButtonやautoCloseなど、boolean型で設定されるプロパティは、全てこの「l」の中に初期設定されているので、そこを編集すれば、動きます。
! function(){
// 略
l = {
// 略
minDate:minDateInput,
maxDate:maxDateInput,
}
//略
}
###onSelectイベント時に値を取得、外部関数で処理
jsで値をリアルタイムに処理したいので、値を取得する関数を、ぶち込みます。
もし、rangeをtrueにしてるときなどは、変数を二つ用意するか、配列にして取得してください。
var getSelectedDate;
var _getDateValue = function _getDateValue(v){
getSelectedDate = v;
return getSelectedDate;
}
引数「t」がどうやら、選択された日付のようです。
selectDate: function (t) {
_getDateValue(t);
//略
}
###onHide,onShowイベント時にも、データ処理用の関数を忍ばせる
もし、表示,非表示の時に処理を追加したいときは、こちらをお使いください。
ただ、重すぎる処理を走らせると、ラグが生じてなんともUIよろしくない感じになりますので注意。
hide: function () {
//適当な関数
}
###閉じるボタンを無理やり追加
AIR DATEPICKERは、クリアボタンは設定できますが、閉じるボタンは筆者が探した感じ、ありません。
閉じるイベントはあるのですが、「ボタンもDatePickerのなかに入れたい」という人は、
素直にぶち込みましょう。
「i」のところに、buttonsというdivがあり、その中に別の変数で、clearbuttonが挿入されているようなので、中に予め一つ追加しておきます。クラス名やidは適宜つけてください。
function () {
var //略,
i = '
<div class="datepicker--buttons">
<button type="button" id="js-dp-close" class="js-dp-close datepicker--button">閉じる</button>
</div>';
//略
}
ただ、掲題の通り、js制御不可な状態なので、css周りをいじって、むりくり消す仕様を作ります。
まず、ライブラリのHideイベントの記載されている箇所から、cssを直接いじってるプロパティを削除します。
hide: function () {
//略
this.$datepicker.removeClass("active").css({
//left: "-100000px" <- 削除
}),
//略
ここで、「active」というクラス名の着脱が行われていることがわかるので、cssで上書きしていきます。
「pointer-events」と「visibility」で、ポインター(クリック・タッチ)とフォーカス両方、打ち消しておくと、アクセシビリティてきに、良いかと思います。
.datepicker{
/* 略 */
left:-100000px;
pointer-events: none;
visibility: none;
opacity: 0;
}
.datepicker.active{
/* 略 */
pointer-events: fill;
visibility: visible;
opacity: 1;
}
###クリック時にスマホだと画面にカレンダーが収まらないので、スクロール関数を付与
スマートフォンとかだと、inputをタッチすると、画面の外にDatePickerが起動してしまうことがあるので、位置までスクロールするようにします。
スクロールはcssだけで実装できますが、polyfillだけ、注意してください。筆者はこれを使っています。
smoothscroll.js
setPosition: function (t) {
//略
window.scrollTo({top:e-80,left:0,behavior:'smooth'});
//e はDatePicker上部のY座標。-80しているのは、マージンです。
}
##終わりに
以上、今回の対応まとめでした。ライブラリは、予期しない挙動をする時があるので、時間がある時orどうしてもやらなきゃいけないときなど、見てみるといいです。勉強し始めの時だと、作者にもよりますが、かなり勉強にもなりました。
コメントいただければ、適宜改訂します。
こういうのを実装したい、などもできるだけ一緒に考えるので、連絡ください。
もし、参考になったよ、というかたがおられましたら、twitterのDMでも、LGTMでも反応いただけると、次回記事のモチベーションになります。
最後までお付き合いいただき、ありがとうございました。