我注意到jQuery datepicker onSelect方法有一个奇怪的行为,你可以看一下this fiddle来测试它。
使用jQuery 1.7.2和jQuery UI 1.8.18进行测试,在Firefox,IE和Chrome中进行。
情景:
如果用鼠标选择日期,一切正常。
这是一个错误吗?如果没有,我该如何避免这种行为?谢谢你的帮助。
答案 0 :(得分:1)
是的,你是对的,即使我在一段时间后得到了这个错误,但却忽视了它。 但是这次我查看了我发现的datepicker脚本,因为它可能是bug。只有在您提到
时才能以特定方式重现你将有两次调用回调函数'onSelect'。
这是因为在datepicker javascript中,'_ selectDate'函数用于获取从键事件处理函数(_doKeyDown() - > _selectDay() - > _selectDate())和两个函数调用的所选日期 调用似乎是bug的回调函数。
更新 -
我修改了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 用户1042031回答了另一种解决方法,但没有完整的解决方案。在这里,您将找到您需要做的事情
$("#datepicker").datepicker({
onSelect: function(dateText,inst) {
$.datepicker._hideDatepicker();
inst.preventDefault();
}
});
你需要删除警告,这会导致在输入字段上设置焦点,这将再次显示datepicker。这是调用onSelect一次,确保在按下回车键后隐藏了日期选择器。
我正在复制解决方案的一部分只是为了兼顾两种方式:)
答案 1 :(得分: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;
}
}
});
尝试这样的事情。我有几分钟的时间来测试它,它似乎工作。如果没有,那就改进想法。
如果你不理解黑客背后的可怕,丑陋的想法,我会解释。
干杯。
答案 2 :(得分: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');
},
});
答案 3 :(得分:0)
目前为止的最佳解决方案:
$("#datepicker").datepicker({
onSelect: function(dateText, inst) {
// do stuff
$.datepicker._hideDatepicker();
inst.preventDefault();
}
});
inst.preventDefault()
是最重要的部分:它会阻止onSelect()
的双重触发。通过使用它,日期选择器在选择日期后不再隐藏,因此您必须致电$.datepicker._hideDatepicker()
来执行此操作。
感谢user1042031和Sunil Chavan。
答案 4 :(得分: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;
});