DatepickerをjQuery 4対応のために`datepicker('show')`に変更
Active Adminは、jQuery UIのDatepickerを遅延初期化する際の表示方法を triggerHandler('focus') から datepicker('show') に変更しました。これはjQuery 4.0.0でDatepickerが初回フォーカス時に開かない問題への対応です。
背景
Active AdminではDatepickerを遅延初期化するパターンを採用しています。入力フィールドに初めてフォーカスが当たったときにDatepickerを作成し、そのまま表示する実装です。
jQuery 3.7.1では triggerHandler('focus') を呼び出すことでDatepickerが開きましたが、jQuery 4.0.0ではこの方法が機能しなくなりました。初回フォーカス時にDatepickerは作成されるものの表示されず、ユーザーは一度ブラー→再フォーカスする必要がありました。この問題は jquery/jquery-ui#2385 で報告されています。
この変更により、jQuery 3と4の両方で一貫した動作が保証されます。
技術的な変更
app/assets/javascripts/active_admin/base.js と app/javascript/active_admin/initializers/datepicker.js の2ファイルで、Datepickerを表示するメソッド呼び出しが変更されました。
変更前:
$(document)
.on('focus', 'input.datepicker:not(.hasDatepicker)', function() {
const input = $(this);
if (input[0].type === 'date') { return; }
const defaults = { dateFormat: 'yy-mm-dd' };
const options = input.data('datepicker-options');
input.datepicker($.extend(defaults, options));
// See https://github.com/jquery/jquery-ui/issues/2385
input.triggerHandler('focus');
});
変更後:
$(document)
.on('focus', 'input.datepicker:not(.hasDatepicker)', function() {
const input = $(this);
if (input[0].type === 'date') { return; }
const defaults = { dateFormat: 'yy-mm-dd' };
const options = input.data('datepicker-options');
input.datepicker($.extend(defaults, options));
// See https://github.com/jquery/jquery-ui/issues/2385
input.datepicker('show');
});
triggerHandler('focus') は間接的にDatepickerの内部ロジックに依存していましたが、datepicker('show') はDatepicker APIの公開メソッドを直接呼び出します。これにより、jQueryのバージョンによるイベント処理の違いの影響を受けなくなります。
PR本文によると、この変更はjQuery 3と4の両方で動作確認されています。
設計判断
公開APIメソッドの使用 という原則に基づいた変更です。
triggerHandler はjQueryのイベントシステムを経由した間接的なアプローチであり、実装の内部動作に依存していました。jQuery 4でのイベント処理の変更により、この依存関係が破綻しました。
一方、datepicker('show') はjQuery UIが提供する公式のインターフェースであり、ライブラリのバージョン間で安定した動作が期待できます。コメントで jquery/jquery-ui#2385 への参照を残すことで、この変更の背景を後から追跡可能にしています。
この判断は、外部ライブラリに依存する際の一般的なベストプラクティス——公開APIを使用し、実装の詳細に依存しない——を適用したものといえます。
まとめ
本PRは、jQuery 4との互換性問題を解決するために、Datepickerの表示方法をより明示的なAPIに切り替えた変更です。triggerHandler('focus') という間接的な方法から datepicker('show') という直接的な方法に変更することで、jQueryのバージョンアップに対する耐性を高めています。