3

jQuery の datepicker の onSelect メソッドの奇妙な動作に気付きました。このフィドルを見てテストできます。

jQuery 1.7.2 および jQuery UI 1.8.18 でテスト済み。Firefox、IE、および Chrome で発生します。

シナリオ:

  1. テキスト フィールドにフォーカスを置きます (日付ピッカーが表示されます)。
  2. Enter キーを押してデフォルトの日付を選択します ( datepicker APIで実行可能と表示されているため)。
  3. onSelect が 2 回呼び出されることに注意してください。

マウスで日付を選択すると、すべて正常に動作します。

これはバグですか?そうでない場合、どうすればこの動作を回避できますか? ご協力いただきありがとうございます。

4

5 に答える 5

1

私はそれを投稿するのが半分恥ずかしいほど醜い解決策の提案を持っています。しかし、絶望的な時代には必死の対策が必要です。

var trigger = false;
var previousDate = "";

$("#datepicker").datepicker({

    onSelect: function(dateText, inst) {

        if (!trigger || (previousDate != dateText)) {
            // Do whatever you want to do
            alert("fire!");
            // I decided to alert
            trigger = true;
            previousDate = dateText;
        } else {
            trigger = false; 
        }
    }
});​

このようなことを試してください。テストするのに数分かかりましたが、うまくいくようです。そうでない場合は、アイデアを改善します。

ハッキングの背後にあるひどく醜いアイデアを理解していない場合は、説明します。

乾杯。

于 2012-07-04T10:32:00.723 に答える
1

はい、あなたは正しいです。私はこのエラーをしばらく前に受け取りましたが、それを無視しました。しかし今回は、バグの可能性があるため、見つけたdatepickerスクリプトを調べました。これは、あなたが言及したように、特定の方法でのみ再現可能です

  • フィールドをクリックするか、タブを使用してフォーカスを移動します
  • エンターを押す

コールバック関数「onSelect」が 2 回呼び出されます。

これは、datepicker JavaScript では、'_selectDate' 関数を使用して、キー イベント ハンドラー関数 (_doKeyDown()->_selectDay()->_selectDate()) から呼び出される選択された日付を取得し、両方の関数がコールバック関数を呼び出すためです。バグのようです。


アップデート -

jquery.ui.datepicker.js ファイルの _doKeyDown 関数を変更しました。イベントがenter(keycode-13)のときのコードを修正しました。したがって、コールバック関数「onSelect」は上記のシナリオで 1 回呼び出されます。

バージョン 1.8.21 のコードは次のとおりです。

_doKeyDown: function(event) {
        var inst = $.datepicker._getInst(event.target);
        var handled = true;
        var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
        inst._keyEvent = true;
        if ($.datepicker._datepickerShowing)
            switch (event.keyCode) {
                case 9: $.datepicker._hideDatepicker();
                        handled = false;
                        break; // hide on tab out
                case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + 
                                    $.datepicker._currentClass + ')', inst.dpDiv);
                        //Update by Sunil start
                        if (sel[0]){
                            $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
                        }else{
                            $.datepicker._hideDatepicker();
                            return true;
                        }
                        //Update by Sunil end
                        return false;
                        break; // select the value on enter
                case 27: $.datepicker._hideDatepicker();
                        break; // hide on escape
                case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
                            -$.datepicker._get(inst, 'stepBigMonths') :
                            -$.datepicker._get(inst, 'stepMonths')), 'M');
                        break; // previous month/year on page up/+ ctrl
                case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
                            +$.datepicker._get(inst, 'stepBigMonths') :
                            +$.datepicker._get(inst, 'stepMonths')), 'M');
                        break; // next month/year on page down/+ ctrl
                case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
                        handled = event.ctrlKey || event.metaKey;
                        break; // clear on ctrl or command +end
                case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
                        handled = event.ctrlKey || event.metaKey;
                        break; // current on ctrl or command +home
                case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
                        handled = event.ctrlKey || event.metaKey;
                        // -1 day on ctrl or command +left
                        if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
                                    -$.datepicker._get(inst, 'stepBigMonths') :
                                    -$.datepicker._get(inst, 'stepMonths')), 'M');
                        // next month/year on alt +left on Mac
                        break;
                case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
                        handled = event.ctrlKey || event.metaKey;
                        break; // -1 week on ctrl or command +up
                case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
                        handled = event.ctrlKey || event.metaKey;
                        // +1 day on ctrl or command +right
                        if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
                                    +$.datepicker._get(inst, 'stepBigMonths') :
                                    +$.datepicker._get(inst, 'stepMonths')), 'M');
                        // next month/year on alt +right
                        break;
                case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
                        handled = event.ctrlKey || event.metaKey;
                        break; // +1 week on ctrl or command +down
                default: handled = false;
            }
        else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
            $.datepicker._showDatepicker(this);
        else {
            handled = false;
        }
        if (handled) {
            event.preventDefault();
            event.stopPropagation();
        }
    },

これで問題が解決することを願っています。


更新 2 user1042031 が回答した別の回避策がありますが、完全な解決策ではありません。ここでは、何をする必要があるかを見つけることができます

$("#datepicker").datepicker({
     onSelect: function(dateText,inst) {       
         $.datepicker._hideDatepicker();
         inst.preventDefault();
    }
});

日付ピッカーを再度表示する入力フィールドにフォーカスを設定するアラートを削除する必要があります。これは、Enterキーを押した後に日付ピッカーを確実に非表示にするために、onSelectを1回呼び出します。

デモ

両方の作業方法を持つためだけに、ソリューションの一部をコピーしています:)

于 2012-07-04T10:27:59.317 に答える
0

使用する

 inst.preventDefault();

このような:

  $("#datepicker").datepicker({
     onSelect: function(dateText,inst) {       
         alert('s');
         inst.preventDefault();
    }
}); 

編集:日付の選択後にカレンダーを削除するには

回避策として、removeclass を使用する必要があります。

 $( "#datepicker" ).datepicker({

       onSelect: function(dateText, inst) {          
       $(inst.dpDiv).find('.ui-state-highlight.ui-state-hover').removeClass('ui-state-highlight ui-state-hover');          

 },
});
于 2012-07-04T12:04:12.587 に答える
0

これまでの最良の解決策:

$("#datepicker").datepicker({
    onSelect: function(dateText, inst) {
        // do stuff
        $.datepicker._hideDatepicker();
        inst.preventDefault();
    }

});

inst.preventDefault()は最も重要な部分です: の二重発火を防ぎonSelect()ます。これを使用すると、日付が選択されると日付ピッカーが非表示になることがなくなるため、呼び出す必要が$.datepicker._hideDatepicker()あります。

user1042031 と Sunil Chavan に感謝します。

于 2012-07-04T14:57:29.983 に答える