【问题标题】:jQuery UI datepicker: onSelect called twicejQuery UI datepicker:onSelect 调用了两次
【发布时间】:2012-07-04 08:54:10
【问题描述】:

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

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

场景:

  1. 将焦点放在文本字段上(应出现日期选择器)
  2. 按回车键选择默认日期(如the datepicker API所说可以做到)
  3. 注意 onSelect 被调用了两次。

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

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

【问题讨论】:

  • 我在 mac osx safari Version 5.1.6 只有一个选择?嗯
  • 是的,它发生在我的 Firefox 11.0 中。不知道为什么。

标签: javascript jquery jquery-ui jquery-ui-datepicker enter


【解决方案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; 
        }
    }
});​

试试这样的。我有几分钟的时间来测试它,它似乎有效。如果没有,请改进这个想法。

如果你不理解黑客背后的可怕、丑陋的想法,我会解释。

干杯。

【讨论】:

  • 是的,我使用了这种变通方法,如果它很难看,它正在工作......但我不得不使用setTimeout(function() { trigger = true; }, 1000);,这更难看。如果我不这样做,该方法仍然被触发了两次。
  • @Virginie 我已修改我的答案以解决此问题。它可能会帮助你。
【解决方案2】:

是的,你是对的,即使我前段时间也遇到过这个错误,但只是忽略了它。 但是这次我查看了我发现的 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 调用,确保在按下回车键后隐藏日期选择器。

DEMO

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

【讨论】:

  • 干得好,但我宁愿不修改源代码;如果有人更改/升级 datepicker 文件,我不希望此问题再次出现。还是谢谢
【解决方案3】:

使用

 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');          

 },
});

【讨论】:

  • 太好了,这似乎是完美的解决方案!我觉得我必须处理 preventDefault() 但不知道如何处理它。谢谢!
  • 更新:我太快了:它几乎是完美的解决方案。没有第二次调用,但是一旦选择了日期,日期选择器就不再隐藏了。不错的尝试:)
  • 您需要在选择日期后删除日期选择器,但您的 qn 是要触发两次还是删除日期选择器?
  • @Virginie 你可以添加 '$.datepicker._hideDatepicker();'在调用 preventDefault() 之前。删除警报,因为它会导致将焦点设置在将再次显示 datepicker 的输入字段上。 :) 连我的回答也是可以接受的:)
  • 我的问题是关于双重触发,同时保持日期选择器的默认行为,即在选择日期后消失。您的解决方案和 @SunilChavan 的解决方案之间的混合是最优雅的方式。
【解决方案4】:

迄今为止最好的解决方案:

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

});

inst.preventDefault()是最重要的部分:它可以防止onSelect()的双重触发。通过使用它,日期选择器在选择日期后不再隐藏,因此您必须调用$.datepicker._hideDatepicker() 来执行此操作。

感谢 user1042031 和 Sunil Chavan。

【讨论】:

  • 我已经在我的帖子中更新了相同的答案。甚至我的回答也解释了问题的根本原因及其解决方法以及解决方法.. :(
【解决方案5】:

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

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;


});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 2011-10-07
    • 2017-06-25
    • 2013-01-21
    相关资源
    最近更新 更多