3

我注意到 jQuery datepicker onSelect 方法有一个奇怪的行为,你可以看看这个 fiddle来测试它。

使用 jQuery 1.7.2 和 jQuery UI 1.8.18 测试,在 Firefox、IE 和 Chrome 中进行。

设想:

  1. 将焦点放在文本字段上(应该出现日期选择器)
  2. 按 enter 选择默认日期(正如datepicker API所说的那样)
  3. 注意 onSelect 被调用了两次。

如果您用鼠标选择日期,一切正常。

这是一个错误吗?如果没有,我该如何避免这种行为?谢谢你的帮助。

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”。

这是因为在 datepicker javascript 中,'_selectDate' 函数用于获取从关键事件处理函数(_doKeyDown()->_selectDay()->_selectDate()) 调用的选定日期,并且两个函数都调用回调函数似乎是错误。


更新 -

我已经修改了 jquery.ui.datepicker.js 文件中的 _doKeyDown 函数。输入事件时我已经修改了代码(keycode-13)。所以现在回调函数'onSelect'在上述场景中被调用一次。

这是版本 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();
    }
});

您需要删除导致将焦点设置在输入字段上的警报,该字段将再次显示日期选择器。这是一次调用 onSelect 以确保在按下回车键后隐藏日期选择器。

演示

我正在复制解决方案的一部分只是为了有两种工作方式:)

于 2012-07-04T10:27:59.317 回答
0

The best solution so far:

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

});

inst.preventDefault()is the most important part: it prevents the double firing of onSelect(). By using it, the datepicker doesn't hide anymore once the date is selected, so you have to call $.datepicker._hideDatepicker() to do it.

Thanks to user1042031 and Sunil Chavan.

于 2012-07-04T14:57:29.983 回答
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

对我来说似乎是一个错误......我把它与各种异步调用联系起来,它把一切都搞砸了......我想出的最好的解决方案是:

jQuery(".date-picker").each(function (index, item) {
    jQuery(item).removeClass("date-picker");
     item.ondpchange = item.onchange;
    jQuery(item).datepicker({
        format: "mm/dd/yyyy",
        autoclose: true,
        todayHighlight: true,

    }).on('changeDate', function (e) {
        if (item.ondpchange != null) {
            item.ondpchange();
        }
    });;
    item.onchange = null;


});
于 2019-06-20T15:14:53.607 回答