Javascript 具有动态元素的表单中的日期时间选择器
Javascript Datetimepicker in form with dynamic elements
我在我的项目中使用 http://eonasdan.github.io/bootstrap-datetimepicker/。很好。
在一个页面上,我有一个表单,其中可以动态添加或删除多行输入字段。在每一行中都有一个 "startdate" 和一个 "enddate" 输入,称为 #substitute_0_start 和 #substitute_0_end.当 cloneNode() 运行时,ID 增加 javascript。 IE。在一个克隆之后,还有一行包含#substitute_1_start和#substitute_1_end。
我需要调整 "startdate" 和 "enddate" 输入的设置。我使用 for 循环遍历每一行并调整设置。这按预期工作,而不是如果我尝试设置相应输入的 minDate 或 maxDate。
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_start" class="control-label">ab dem</label>
<div class='input-group date substitute_start' id='substitute_0_start'>
<input type="text" class="form-control datepicker subst_start" name="substitute[0][start]" readonly="readonly"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_end" class="control-label">bis zum</label>
<div class='input-group date substitute_end' id='substitute_0_end'>
<input type="text" class="form-control datepicker subst_end" name="substitute[0][end]" readonly="readonly"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
function callDatepickerAndSelect2(){
for (a = 0; a <= i; a++){
// WORKS!
$('#substitute_'+a+'_start').datetimepicker({
format: "DD.MM.YYYY",
minDate: moment().add(1, 'minutes')
});
$('#substitute_'+a+'_end').datetimepicker({
format: "DD.MM.YYYY",
minDate: moment().add(1, 'days')
});
// WORKS NOT FOR CLONED ITEMS
$("#interval_start").on("dp.change", function (e) {
$('.substitute_start').data("DateTimePicker").minDate(e.date);
$('.substitute_end').data("DateTimePicker").minDate(e.date);
});
$("#interval_end").on("dp.change", function (e) {
$('.substitute_start').data("DateTimePicker").maxDate(e.date);
$('.substitute_end').data("DateTimePicker").maxDate(e.date);
});
// THIS DOES NOT WORK!
$("#substitute_"+a+"_start").on("dp.change", function (e) {
$("#substitute_"+ a +"_end").data("DateTimePicker").minDate(e.date);
});
$("#substitute_"+a+"_end").on("dp.change", function (e) {
$("#substitute_"+ a +"_start").data("DateTimePicker").maxDate(e.date);
});
};
}
每次触发最后两个 dp.change() 时,我都会收到错误 Cannot read 属性 'minDate' of undefined 或无法读取未定义 的 属性 'maxDate'。
我找不到如何设置 maxDate of #substitute_X_end if #substitute_X_start 的解决方案改变了(当然诅咒另一个方向)。
有没有人知道最初将 maxDate/minDate 设置为相应的输入以及我是否执行了 cloneNode()?
编辑
我还调查过,中间部分不适用于克隆元素。
对我来说,感觉克隆的元素是自己可见的,但我无法使用 javascript 访问它们。我想我需要另一种解决方案来克隆整个 DIV :-(
编辑 2
我设置了一个 fiddle。在此处结帐 https://jsfiddle.net/qs8kf6wj/
(抱歉,日期时间选择器在那里不起作用,无法找出原因)
首先我发现您的代码存在一些问题:
在 callDatepickerAndSelect2
上,您要求的是 substitute_start
和 substitute_end
的日期,而不是 parents,并且您一遍又一遍地绑定事件每添加一个新元素,这都不是个好主意
所以我对代码做了一些修改,希望清楚:
1) 无需再次调用和重新绑定每个元素,只需调用当前被i
持有的元素
2) 允许使用 allowInputToggle
and ignoreReadonly
的只读字段更改日期
3) 当在 parents 中完成日期更改时,调用更新子项 (Sub-intervals) updateRangeMin
和 updateRangeMax
[=23= 的函数]
4) 对于新的孩子,发送当前选择的日期,以便它可以从 current_min
和 current_max
代表的范围开始
5) 不要在HTML里面调用JavaScript,这没有错,但是看起来确实很糟糕
$(document).ready(function() {
$("#interval_start").datetimepicker({
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$("#interval_end").datetimepicker({
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$("#interval_start").on("dp.change", function(e) {
current_min = e.date;
$("#interval_end")
.data("DateTimePicker")
.minDate(e.date);
updateRangeMin(e.date);
});
$("#interval_end").on("dp.change", function(e) {
current_max = e.date;
$("#interval_start")
.data("DateTimePicker")
.maxDate(e.date);
updateRangeMax(e.date);
});
callDatepickerAndSelect2(i);
});
function updateRangeMin(date) {
for (let index = 0; index <= i; index++) {
$("#substitute_" + index + "_start")
.data("DateTimePicker")
.minDate(date);
}
}
function updateRangeMax(date) {
for (let index = 0; index <= i; index++) {
$("#substitute_" + index + "_end")
.data("DateTimePicker")
.maxDate(date);
}
}
var i = 0;
var original = document.getElementById("substitute_0");
let current_min = null;
let current_max = null;
function duplicateElement() {
var clone = original.cloneNode(true); // "deep" clone
i++;
clone.id = "substitute_" + i; // there can only be one element with an ID
clone.childNodes;
for (var input of $(".substitute_start", clone)) {
input.id = clone.id + "_start";
}
for (var input of $(".substitute_end", clone)) {
input.id = clone.id + "_end";
}
for (var input of $(".subst_text", clone)) {
input.name = "substitute[" + i + "][text]";
}
for (var input of $(".subst_start", clone)) {
input.name = "substitute[" + i + "][start]";
}
for (var input of $(".subst_end", clone)) {
input.name = "substitute[" + i + "][end]";
}
original.parentNode.appendChild(clone);
callDatepickerAndSelect2(i);
}
function removeElement(elementId) {
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
function callDatepickerAndSelect2(a) {
let start_element = "#substitute_" + a + "_start";
let end_element = "#substitute_" + a + "_end";
$(start_element).datetimepicker({
maxDate: current_max,
minDate: current_min,
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$(end_element).datetimepicker({
maxDate: current_max,
minDate: current_min,
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$(start_element).on("dp.change", function(e) {
$(end_element)
.data("DateTimePicker")
.minDate(e.date);
});
$(end_element).on("dp.change", function(e) {
$(start_element)
.data("DateTimePicker")
.maxDate(e.date);
});
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js"></script>
<div class="container">
<h2>
Main Interval
</h2>
This two dates are minDate and maxDate for all Sub-Intervals!
<div class="row">
<div class="form-group col-sm-6">
<label for="interval_start" class="control-label">Interval start</label
>
<div class="input-group date" id="interval_start">
<input
type="text"
class="form-control datepicker"
name="interval_start"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="form-group col-sm-6">
<label for="interval_end" class="control-label">Interval end</label>
<div class="input-group date" id="interval_end">
<input type="text" class="form-control datepicker" name="interval_end" readonly="readonly" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<h2>
Sub-Intervals (n-times)
</h2>
<div class="row" style="border: 2px solid #0F0;">
<div id="substitute_0" class="">
<div class="panel-body">
Each interval has to fit in the Main-Interval and has to fit: startdate
< enddate and enddate> startdate
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_start" class="control-label">ab dem</label
>
<div
class="input-group date substitute_start"
id="substitute_0_start"
>
<input
type="text"
class="form-control datepicker subst_start"
name="substitute[0][start]"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_end" class="control-label"
>bis zum</label
>
<div
class="input-group date substitute_end"
id="substitute_0_end"
>
<input
type="text"
class="form-control datepicker subst_end"
name="substitute[0][end]"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<hr />
</div>
</div>
<div class="row">
<div class="input-group pull-right">
add sub-interval
<button
type="button"
class="btn btn-default"
onclick="duplicateElement();"
>
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
</div>
</div>
更好一点,没有问题 minDate 和 maxDate 以及更多改进!
$(document).ready(function() {
$("#interval_start").datetimepicker({
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$("#interval_end").datetimepicker({
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$("#interval_start").on("dp.change", function(e) {
current_min = e.date.startOf("day");
$("#interval_end")
.data("DateTimePicker")
.minDate(e.date);
updateRangeMin(e.date);
});
$("#interval_end").on("dp.change", function(e) {
current_max = e.date.endOf("day");
$("#interval_start")
.data("DateTimePicker")
.maxDate(e.date);
updateRangeMax(e.date);
});
callDatepickerAndSelect2(i);
});
function updateRangeMin(date) {
for (let index = 0; index <= i; index++) {
var temp = new moment(date);
if($("#substitute_" + index + "_start").data("DateTimePicker").maxDate().isBefore(date)){
//for fixing maxDate is before minDate error
$("#substitute_" + index + "_start").data("DateTimePicker").maxDate(temp.add(1825, "days"));
}
$("#substitute_" + index + "_start")
.data("DateTimePicker")
.minDate(date);
if($("#substitute_" + index + "_end").data("DateTimePicker").maxDate().isBefore(date)){
//for fixing maxDate is before minDate error
$("#substitute_" + index + "_end").data("DateTimePicker").maxDate(temp.add(1825, "days"));
}
$("#substitute_" + index + "_end")
.data("DateTimePicker")
.minDate(date);
}
}
function updateRangeMax(date) {
for (let index = 0; index <= i; index++) {
$("#substitute_" + index + "_end")
.data("DateTimePicker")
.maxDate(date);
$("#substitute_" + index + "_start")
.data("DateTimePicker")
.maxDate(date);
}
}
var i = 0;
var original = document.getElementById("substitute_0");
let current_min = null;
let current_max = null;
function duplicateElement() {
var clone = original.cloneNode(true); // "deep" clone
i++;
clone.id = "substitute_" + i; // there can only be one element with an ID
clone.childNodes;
for (var input of $(".substitute_start", clone)) {
input.id = clone.id + "_start";
}
for (var input of $(".substitute_end", clone)) {
input.id = clone.id + "_end";
}
for (var input of $(".subst_text", clone)) {
input.name = "substitute[" + i + "][text]";
}
for (var input of $(".subst_start", clone)) {
input.name = "substitute[" + i + "][start]";
}
for (var input of $(".subst_end", clone)) {
input.name = "substitute[" + i + "][end]";
}
for (var input of $(".subst_text", clone)) {
input.value = "";
}
for (var input of $(".subst_start", clone)) {
input.value = "";
}
for (var input of $(".subst_end", clone)) {
input.value = "";
}
original.parentNode.appendChild(clone);
callDatepickerAndSelect2(i);
}
function removeElement(elementId) {
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
function callDatepickerAndSelect2(a) {
let start_element = "#substitute_" + a + "_start";
let end_element = "#substitute_" + a + "_end";
$(start_element).datetimepicker({
maxDate: current_max,
minDate: current_min,
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$(end_element).datetimepicker({
maxDate: current_max,
minDate: current_min,
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$(start_element).on("dp.change", function(e) {
$(end_element)
.data("DateTimePicker")
.minDate(e.date);
});
$(end_element).on("dp.change", function(e) {
$(start_element)
.data("DateTimePicker")
.maxDate(e.date);
});
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js"></script>
<div class="container">
<h2>
Main Interval
</h2>
This two dates are minDate and maxDate for all Sub-Intervals!
<div class="row">
<div class="form-group col-sm-6">
<label for="interval_start" class="control-label">Interval start</label
>
<div class="input-group date" id="interval_start">
<input
type="text"
class="form-control datepicker"
name="interval_start"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="form-group col-sm-6">
<label for="interval_end" class="control-label">Interval end</label>
<div class="input-group date" id="interval_end">
<input type="text" class="form-control datepicker" name="interval_end" readonly="readonly" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<h2>
Sub-Intervals (n-times)
</h2>
<div class="row" style="border: 2px solid #0F0;">
<div id="substitute_0" class="">
<div class="panel-body">
Each interval has to fit in the Main-Interval and has to fit: startdate
< enddate and enddate> startdate
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_start" class="control-label">ab dem</label
>
<div
class="input-group date substitute_start"
id="substitute_0_start"
>
<input
type="text"
class="form-control datepicker subst_start"
name="substitute[0][start]"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_end" class="control-label"
>bis zum</label
>
<div
class="input-group date substitute_end"
id="substitute_0_end"
>
<input
type="text"
class="form-control datepicker subst_end"
name="substitute[0][end]"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<hr />
</div>
</div>
<div class="row">
<div class="input-group pull-right">
add sub-interval
<button
type="button"
class="btn btn-default"
onclick="duplicateElement();"
>
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
</div>
</div>
我在我的项目中使用 http://eonasdan.github.io/bootstrap-datetimepicker/。很好。
在一个页面上,我有一个表单,其中可以动态添加或删除多行输入字段。在每一行中都有一个 "startdate" 和一个 "enddate" 输入,称为 #substitute_0_start 和 #substitute_0_end.当 cloneNode() 运行时,ID 增加 javascript。 IE。在一个克隆之后,还有一行包含#substitute_1_start和#substitute_1_end。
我需要调整 "startdate" 和 "enddate" 输入的设置。我使用 for 循环遍历每一行并调整设置。这按预期工作,而不是如果我尝试设置相应输入的 minDate 或 maxDate。
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_start" class="control-label">ab dem</label>
<div class='input-group date substitute_start' id='substitute_0_start'>
<input type="text" class="form-control datepicker subst_start" name="substitute[0][start]" readonly="readonly"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_end" class="control-label">bis zum</label>
<div class='input-group date substitute_end' id='substitute_0_end'>
<input type="text" class="form-control datepicker subst_end" name="substitute[0][end]" readonly="readonly"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
function callDatepickerAndSelect2(){
for (a = 0; a <= i; a++){
// WORKS!
$('#substitute_'+a+'_start').datetimepicker({
format: "DD.MM.YYYY",
minDate: moment().add(1, 'minutes')
});
$('#substitute_'+a+'_end').datetimepicker({
format: "DD.MM.YYYY",
minDate: moment().add(1, 'days')
});
// WORKS NOT FOR CLONED ITEMS
$("#interval_start").on("dp.change", function (e) {
$('.substitute_start').data("DateTimePicker").minDate(e.date);
$('.substitute_end').data("DateTimePicker").minDate(e.date);
});
$("#interval_end").on("dp.change", function (e) {
$('.substitute_start').data("DateTimePicker").maxDate(e.date);
$('.substitute_end').data("DateTimePicker").maxDate(e.date);
});
// THIS DOES NOT WORK!
$("#substitute_"+a+"_start").on("dp.change", function (e) {
$("#substitute_"+ a +"_end").data("DateTimePicker").minDate(e.date);
});
$("#substitute_"+a+"_end").on("dp.change", function (e) {
$("#substitute_"+ a +"_start").data("DateTimePicker").maxDate(e.date);
});
};
}
每次触发最后两个 dp.change() 时,我都会收到错误 Cannot read 属性 'minDate' of undefined 或无法读取未定义 的 属性 'maxDate'。
我找不到如何设置 maxDate of #substitute_X_end if #substitute_X_start 的解决方案改变了(当然诅咒另一个方向)。
有没有人知道最初将 maxDate/minDate 设置为相应的输入以及我是否执行了 cloneNode()?
编辑 我还调查过,中间部分不适用于克隆元素。 对我来说,感觉克隆的元素是自己可见的,但我无法使用 javascript 访问它们。我想我需要另一种解决方案来克隆整个 DIV :-(
编辑 2 我设置了一个 fiddle。在此处结帐 https://jsfiddle.net/qs8kf6wj/ (抱歉,日期时间选择器在那里不起作用,无法找出原因)
首先我发现您的代码存在一些问题:
在 callDatepickerAndSelect2
上,您要求的是 substitute_start
和 substitute_end
的日期,而不是 parents,并且您一遍又一遍地绑定事件每添加一个新元素,这都不是个好主意
所以我对代码做了一些修改,希望清楚:
1) 无需再次调用和重新绑定每个元素,只需调用当前被i
2) 允许使用 allowInputToggle
and ignoreReadonly
3) 当在 parents 中完成日期更改时,调用更新子项 (Sub-intervals) updateRangeMin
和 updateRangeMax
[=23= 的函数]
4) 对于新的孩子,发送当前选择的日期,以便它可以从 current_min
和 current_max
代表的范围开始
5) 不要在HTML里面调用JavaScript,这没有错,但是看起来确实很糟糕
$(document).ready(function() {
$("#interval_start").datetimepicker({
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$("#interval_end").datetimepicker({
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$("#interval_start").on("dp.change", function(e) {
current_min = e.date;
$("#interval_end")
.data("DateTimePicker")
.minDate(e.date);
updateRangeMin(e.date);
});
$("#interval_end").on("dp.change", function(e) {
current_max = e.date;
$("#interval_start")
.data("DateTimePicker")
.maxDate(e.date);
updateRangeMax(e.date);
});
callDatepickerAndSelect2(i);
});
function updateRangeMin(date) {
for (let index = 0; index <= i; index++) {
$("#substitute_" + index + "_start")
.data("DateTimePicker")
.minDate(date);
}
}
function updateRangeMax(date) {
for (let index = 0; index <= i; index++) {
$("#substitute_" + index + "_end")
.data("DateTimePicker")
.maxDate(date);
}
}
var i = 0;
var original = document.getElementById("substitute_0");
let current_min = null;
let current_max = null;
function duplicateElement() {
var clone = original.cloneNode(true); // "deep" clone
i++;
clone.id = "substitute_" + i; // there can only be one element with an ID
clone.childNodes;
for (var input of $(".substitute_start", clone)) {
input.id = clone.id + "_start";
}
for (var input of $(".substitute_end", clone)) {
input.id = clone.id + "_end";
}
for (var input of $(".subst_text", clone)) {
input.name = "substitute[" + i + "][text]";
}
for (var input of $(".subst_start", clone)) {
input.name = "substitute[" + i + "][start]";
}
for (var input of $(".subst_end", clone)) {
input.name = "substitute[" + i + "][end]";
}
original.parentNode.appendChild(clone);
callDatepickerAndSelect2(i);
}
function removeElement(elementId) {
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
function callDatepickerAndSelect2(a) {
let start_element = "#substitute_" + a + "_start";
let end_element = "#substitute_" + a + "_end";
$(start_element).datetimepicker({
maxDate: current_max,
minDate: current_min,
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$(end_element).datetimepicker({
maxDate: current_max,
minDate: current_min,
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$(start_element).on("dp.change", function(e) {
$(end_element)
.data("DateTimePicker")
.minDate(e.date);
});
$(end_element).on("dp.change", function(e) {
$(start_element)
.data("DateTimePicker")
.maxDate(e.date);
});
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js"></script>
<div class="container">
<h2>
Main Interval
</h2>
This two dates are minDate and maxDate for all Sub-Intervals!
<div class="row">
<div class="form-group col-sm-6">
<label for="interval_start" class="control-label">Interval start</label
>
<div class="input-group date" id="interval_start">
<input
type="text"
class="form-control datepicker"
name="interval_start"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="form-group col-sm-6">
<label for="interval_end" class="control-label">Interval end</label>
<div class="input-group date" id="interval_end">
<input type="text" class="form-control datepicker" name="interval_end" readonly="readonly" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<h2>
Sub-Intervals (n-times)
</h2>
<div class="row" style="border: 2px solid #0F0;">
<div id="substitute_0" class="">
<div class="panel-body">
Each interval has to fit in the Main-Interval and has to fit: startdate
< enddate and enddate> startdate
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_start" class="control-label">ab dem</label
>
<div
class="input-group date substitute_start"
id="substitute_0_start"
>
<input
type="text"
class="form-control datepicker subst_start"
name="substitute[0][start]"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_end" class="control-label"
>bis zum</label
>
<div
class="input-group date substitute_end"
id="substitute_0_end"
>
<input
type="text"
class="form-control datepicker subst_end"
name="substitute[0][end]"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<hr />
</div>
</div>
<div class="row">
<div class="input-group pull-right">
add sub-interval
<button
type="button"
class="btn btn-default"
onclick="duplicateElement();"
>
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
</div>
</div>
更好一点,没有问题 minDate 和 maxDate 以及更多改进!
$(document).ready(function() {
$("#interval_start").datetimepicker({
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$("#interval_end").datetimepicker({
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$("#interval_start").on("dp.change", function(e) {
current_min = e.date.startOf("day");
$("#interval_end")
.data("DateTimePicker")
.minDate(e.date);
updateRangeMin(e.date);
});
$("#interval_end").on("dp.change", function(e) {
current_max = e.date.endOf("day");
$("#interval_start")
.data("DateTimePicker")
.maxDate(e.date);
updateRangeMax(e.date);
});
callDatepickerAndSelect2(i);
});
function updateRangeMin(date) {
for (let index = 0; index <= i; index++) {
var temp = new moment(date);
if($("#substitute_" + index + "_start").data("DateTimePicker").maxDate().isBefore(date)){
//for fixing maxDate is before minDate error
$("#substitute_" + index + "_start").data("DateTimePicker").maxDate(temp.add(1825, "days"));
}
$("#substitute_" + index + "_start")
.data("DateTimePicker")
.minDate(date);
if($("#substitute_" + index + "_end").data("DateTimePicker").maxDate().isBefore(date)){
//for fixing maxDate is before minDate error
$("#substitute_" + index + "_end").data("DateTimePicker").maxDate(temp.add(1825, "days"));
}
$("#substitute_" + index + "_end")
.data("DateTimePicker")
.minDate(date);
}
}
function updateRangeMax(date) {
for (let index = 0; index <= i; index++) {
$("#substitute_" + index + "_end")
.data("DateTimePicker")
.maxDate(date);
$("#substitute_" + index + "_start")
.data("DateTimePicker")
.maxDate(date);
}
}
var i = 0;
var original = document.getElementById("substitute_0");
let current_min = null;
let current_max = null;
function duplicateElement() {
var clone = original.cloneNode(true); // "deep" clone
i++;
clone.id = "substitute_" + i; // there can only be one element with an ID
clone.childNodes;
for (var input of $(".substitute_start", clone)) {
input.id = clone.id + "_start";
}
for (var input of $(".substitute_end", clone)) {
input.id = clone.id + "_end";
}
for (var input of $(".subst_text", clone)) {
input.name = "substitute[" + i + "][text]";
}
for (var input of $(".subst_start", clone)) {
input.name = "substitute[" + i + "][start]";
}
for (var input of $(".subst_end", clone)) {
input.name = "substitute[" + i + "][end]";
}
for (var input of $(".subst_text", clone)) {
input.value = "";
}
for (var input of $(".subst_start", clone)) {
input.value = "";
}
for (var input of $(".subst_end", clone)) {
input.value = "";
}
original.parentNode.appendChild(clone);
callDatepickerAndSelect2(i);
}
function removeElement(elementId) {
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
function callDatepickerAndSelect2(a) {
let start_element = "#substitute_" + a + "_start";
let end_element = "#substitute_" + a + "_end";
$(start_element).datetimepicker({
maxDate: current_max,
minDate: current_min,
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$(end_element).datetimepicker({
maxDate: current_max,
minDate: current_min,
format: "DD.MM.YYYY",
allowInputToggle: true,
ignoreReadonly: true
});
$(start_element).on("dp.change", function(e) {
$(end_element)
.data("DateTimePicker")
.minDate(e.date);
});
$(end_element).on("dp.change", function(e) {
$(start_element)
.data("DateTimePicker")
.maxDate(e.date);
});
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js"></script>
<div class="container">
<h2>
Main Interval
</h2>
This two dates are minDate and maxDate for all Sub-Intervals!
<div class="row">
<div class="form-group col-sm-6">
<label for="interval_start" class="control-label">Interval start</label
>
<div class="input-group date" id="interval_start">
<input
type="text"
class="form-control datepicker"
name="interval_start"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="form-group col-sm-6">
<label for="interval_end" class="control-label">Interval end</label>
<div class="input-group date" id="interval_end">
<input type="text" class="form-control datepicker" name="interval_end" readonly="readonly" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<h2>
Sub-Intervals (n-times)
</h2>
<div class="row" style="border: 2px solid #0F0;">
<div id="substitute_0" class="">
<div class="panel-body">
Each interval has to fit in the Main-Interval and has to fit: startdate
< enddate and enddate> startdate
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_start" class="control-label">ab dem</label
>
<div
class="input-group date substitute_start"
id="substitute_0_start"
>
<input
type="text"
class="form-control datepicker subst_start"
name="substitute[0][start]"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="form-group col-md-3 col-xs-6">
<label for="substitute_0_end" class="control-label"
>bis zum</label
>
<div
class="input-group date substitute_end"
id="substitute_0_end"
>
<input
type="text"
class="form-control datepicker subst_end"
name="substitute[0][end]"
readonly="readonly"
/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<hr />
</div>
</div>
<div class="row">
<div class="input-group pull-right">
add sub-interval
<button
type="button"
class="btn btn-default"
onclick="duplicateElement();"
>
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
</div>
</div>