我有一个带有日期输入字段的表单。日期应经过验证:仅允许从今天开始的日期+最多3年。如果日期有效,则会显示模态,否则会出现带有错误消息的警报。
假设somone将日期更改为26.10.2099:
如果一个人离开输入字段(通过用鼠标点击其他地方),一切都按预期工作:
但是如果按下Enter而不是仅仅离开输入字段,则会发生以下情况:
我的想法是将日期更改回其初始值会导致再次触发onchange事件,然后日期有效并且模式将显示。但第一种情况并非如此。在第二种情况下,事件会触发两次SOMETIMES但不总是。
你可以在这里试试自己: https://jsfiddle.net/6x9n53fx/3/
或阅读以下代码:
HTML:
<div class="container">
<form method="post" action="" enctype="multipart/form-data">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="review_date">Valid until *</label>
<input id="review_date" type="text" name="review_date" value="26.10.2016" class="form-control">
<p>Please set a validation date. (max 3 years)</p>
</div>
</div>
</div>
</form>
</div>
<!-- Modal -->
<div class="modal fade" id="info_modal" tabindex="-1" role="dialog" aria-labelledby="modal_title">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="modal_title">Dialog</h4>
</div>
<div class="modal-body">
<div class="form-group mbn">
<p class="mb10">Date successfully changed.</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Ok</button>
</div>
</div>
</div>
</div>
使用Javascript:
var datumfeld = $("#review_date");
var initialdatum = datumfeld.val();
var i = 0;
datumfeld.datepicker({
minDate: 0,
maxDate: "3y",
dateFormat: 'dd.mm.yy'
});
datumfeld.change(function() {
i++;
console.log('onchange triggered: ' + i);
if (validateDatum()) {
$("#info_modal").modal({
backdrop: "static",
keyboard: false
});
}
});
function validateDatum() {
var dateParts = datumfeld.val().split(".");
var review_date = new Date(dateParts[2], (dateParts[1] - 1), (parseInt(dateParts[0]) + 1));
if (((new Date(review_date - (new Date()))).getFullYear() - 1970) > 2) {
alert("Error: The date must not exceed 3 years from now.");
datumfeld.val(initialdatum);
return false;
}
if ((review_date - (new Date)) < 0) {
alert("Error: The date must not be in the past.");
datumfeld.val(initialdatum);
return false;
}
return true;
}
修改
以下是我采用的最终解决方案:
datumfeld.on('keydown', function(e) {
// when keydown is ENTER (13)
if (e.keyCode == 13) {
// Hide the datepicker
$(this).datepicker('hide');
// Trigger a change event to trigger the validation
$(this).trigger('change');
}
})
答案 0 :(得分:4)
代码中的问题是当你按输入你的值时!=当你点击其他地方时。您可以在调试dateParts
当您输入示例时:28.10.2099并点击离开dateParts
是[&#34; 28&#34;,&#34; 10&#34;,&#34; 2099&#34;]
但是当输入例子时:28.10.2099并按ENTER键dateParts
是[&#34; 28&#34;,&#34; 10&#34;,&#34; 2019&#34;]这里datepicker验证了输入字段并自动将日期设置为28.10.2019,因为您将maxDate
设置为3y
。
所以我的解决方案是绑定keydown
并绕过datepicker,然后自动更改值。
以下是工作代码的链接:https://jsfiddle.net/95qbs86x/2/
更新:添加了代码
var datumfeld = $("#review_date");
var initialdatum = datumfeld.val();
var i = 0;
// bind keydown event
datumfeld.on('keydown', function(e) {
// when keydown is ENTER (13)
if (e.keyCode == 13) {
// trigger tab to hide datepicker
var e = $.Event("keydown");
e.which = 9; //tab
e.keyCode = 9;
e.key = 'Tab';
$(this).trigger(e);
return false;
}
}).datepicker({
minDate: 0,
maxDate: "3y",
dateFormat: 'dd.mm.yy',
onClose: function(){
this.blur();
}
}).on('change', function(e) {
i++;
console.log('onchange triggered: ' + i);
if (validateDatum()) {
$("#info_modal").modal({
backdrop: "static",
keyboard: false
});
}
});
function validateDatum() {
var dateParts = datumfeld.val().split(".");
console.log(dateParts);
var review_date = new Date(dateParts[2], (dateParts[1] - 1), (parseInt(dateParts[0]) + 1));
if (((new Date(review_date - (new Date()))).getFullYear() - 1970) > 2) {
alert("Error: The date must not exceed 3 years from now.");
datumfeld.val(initialdatum);
return false;
}
if ((review_date - (new Date)) < 0) {
alert("Error: The date must not be in the past.");
datumfeld.val(initialdatum);
return false;
}
return true;
}
注意:有些代码可以删除,例如:e.which = 9;
e.key = 'Tab';
return false;
然而,要应用与点击相同的效果,应添加以下代码:
onClose: function(){
this.blur();
}
一些代码来自这个回答:Disable enter key in JQuery ui datepicker
答案 1 :(得分:0)
你需要使用preventDefault()来处理这个问题,下面给出了工作演示......
$(document).ready(function() {
var datumfeld = $("#review_date");
var initialdatum = datumfeld.val();
var i = 0;
datumfeld.datepicker({
minDate: 0,
maxDate: "3y",
dateFormat: 'dd.mm.yy'
});
datumfeld.change(function(e) {
i++;
console.log('onchange triggered: ' + i);
if (validateDatum()) {
e.preventDefault();
$("#info_modal").modal({
backdrop: "static",
keyboard: false
});
}
});
function validateDatum() {
var dateParts = datumfeld.val().split(".");
var review_date = new Date(dateParts[2], (dateParts[1] - 1), (parseInt(dateParts[0]) + 1));
if (((new Date(review_date - (new Date()))).getFullYear() - 1970) > 2) {
alert("Error: The date must not exceed 3 years from now.");
datumfeld.val(initialdatum);
return false;
}
else if ((review_date - (new Date)) < 0) {
alert("Error: The date must not be in the past.");
datumfeld.val(initialdatum);
return false;
} else {
return true;
}
}
function handleSubmit() {
console.log("form submitted....");
return false;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div class="container">
<form method="post" action="" enctype="multipart/form-data" onsubmit="return handleSubmit();">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="review_date">Valid until *</label>
<input id="review_date" type="text" name="review_date" value="26.10.2016" class="form-control">
<p>Please set a validation date. (max 3 years)</p>
</div>
</div>
</div>
</form>
</div>
<!-- Modal -->
<div class="modal fade" id="info_modal" data-controls-modal="info_modal" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="modal_title" data-keyboard="false">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="modal_title">Dialog</h4>
</div>
<div class="modal-body">
<div class="form-group mbn">
<p class="mb10">Date successfully changed.</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Ok</button>
</div>
</div>
</div>
</div>
解释:
你是正确的将日期更改回其初始值导致onchange事件再次被触发,那时你需要处理这个问题,所以要处理它有一个选项preventDefault(),我已经附加工作您需要的示例和参考,您可以签出这些链接.. Reference_1,Reference_2,Reference_3 ...
答案 2 :(得分:0)
一旦按下&#34;输入&#34;日期选择器就会触发更改事件并在日期不适合日期选择器本身的minDate
或maxDate
时更改日期。
所以我更新了keyup
事件的事件处理程序,并在您使用键盘输入任何内容后立即销毁日期选择器(=&gt;表示您不希望在帮助下输入日期datepicker)我按下ENTER
后重置它。
这是最终的JavaScript代码:
var datumfeld = $("#review_date");
var initialdatum = datumfeld.val();
var i = 0;
datumfeld.datepicker({
minDate: 0,
maxDate: "3y",
dateFormat: 'dd.mm.yy'
});
datumfeld.on('keyup change', function(e) {
e.preventDefault();
if(e.key && e.key === "Enter") {
e.stopImmediatePropagation();
datumfeld.datepicker({
minDate: 0,
maxDate: "3y",
dateFormat: 'dd.mm.yy'
});
} else if(e.key) {
datumfeld.datepicker("destroy");
}
if(!e.key || e.key === "Enter") {
i++;
console.log('onchange triggered: ' + i);
if (validateDatum()) {
$("#info_modal").modal({
backdrop: "static",
keyboard: false
});
}
}
});
function validateDatum() {
var dateParts = datumfeld.val().split(".");
var review_date = new Date(dateParts[2], (dateParts[1] - 1), (parseInt(dateParts[0]) + 1));
if (((new Date(review_date - (new Date()))).getFullYear() - 1970) > 2) {
alert("Error: The date must not exceed 3 years from now.");
datumfeld.val(initialdatum);
return false;
}
if ((review_date - (new Date)) < 0) {
alert("Error: The date must not be in the past.");
datumfeld.val(initialdatum);
return false;
}
return true;
}
不知怎的,.datepicker("destroy")
在JSFiddle上不起作用,但肯定存在:http://api.jqueryui.com/datepicker/#method-destroy
e.stopImmediatePropagation();
只在检查ENTER
密钥时帮助了,但它只能每隔一秒运行一次。有时keyup
更快,有时候是datepicker。这就是我想破坏日期选择器的原因。
答案 3 :(得分:0)
如果动态触发change事件,您将在使用
的事件中获得originalEvent属性if(typeof e.originalEvent!='undefined') return;
取而代之的是防止默认,尽管这两种方式都是相同的https://jsfiddle.net/6x9n53fx/4/