简体   繁体   English

使用事件克隆Eonasdan DateTimePicker

[英]Cloning Eonasdan DateTimePicker with Events

I'm creating a form that has two pickers to calculate the diference between the dates. 我正在创建一个具有两个选择器的表单,以计算日期之间的差异。

The user has the ability to create more date intervals and those should calculate the particular interval. 用户可以创建更多的日期间隔,并且应该计算特定的间隔。

The issue I'm having is: after cloning the pickers no matter what I do, all other cloned pickers activate the first one. 我遇到的问题是:无论我做什么都克隆了选择器之后,所有其他克隆的选择器都会激活第一个选择器。

The calculation happens after page load and the hide event of the pickers. 计算在页面加载和选择器的hide事件之后发生。

I know I have to initialise the new pickers upon creation, and I do it, but I'm not sure if it works. 我知道我必须在创建时初始化新的选择器,并且可以这样做,但是我不确定它是否有效。

How can I make this work? 我该如何进行这项工作? I know that if I remove the true from clone() the pickers work, but then the clone can't activate the events for the calculations. 我知道,如果我从clone()删除true ,则选择器可以工作,但是克隆无法激活用于计算的事件。

 var tomorrow = moment().add(1, 'day'); var startOfYearMoment = moment(tomorrow) var endOfYearMoment = moment(tomorrow.add(1, 'year')); function destroyPickers(nrOfSiblings) { // console.log("DELETED"); for (let i = 0; i < nrOfSiblings; i++) { // console.log(i); $("#inicio" + i).data("DateTimePicker").destroy(); $("#fim" + i).data("DateTimePicker").destroy(); } } function updatePickers(nrOfSiblings) { // console.log("UPDATED"); for (let i = 0; i < nrOfSiblings + 1; i++) { // console.log(i); initDatePickers("inicio" + i, "fim" + i); } } function initDatePickers(idInicio, idFim) { //, parentInicio, parentFim) { $("#" + idInicio).datetimepicker({ locale: 'pt', ignoreReadonly: true, focusOnShow: false, viewMode: 'months', format: 'DD/MM/YYYY', defaultDate: startOfYearMoment, // widgetParent: $(parentInicio), widgetPositioning: { horizontal: 'auto', vertical: 'auto' }, icons: { time: 'calendarIcon time', date: 'calendarIcon date', up: 'calendarIcon up', down: 'calendarIcon down', previous: 'calendarIcon prev', next: 'calendarIcon next', today: 'calendarIcon today', clear: 'calendarIcon clear', close: 'calendarIcon close' } }); $("#" + idFim).datetimepicker({ locale: 'pt', ignoreReadonly: true, focusOnShow: false, viewMode: 'months', format: 'DD/MM/YYYY', defaultDate: endOfYearMoment, // widgetParent: $(parentFim), widgetPositioning: { horizontal: 'auto', vertical: 'auto' }, icons: { time: 'calendarIcon time', date: 'calendarIcon date', up: 'calendarIcon up', down: 'calendarIcon down', previous: 'calendarIcon prev', next: 'calendarIcon next', today: 'calendarIcon today', clear: 'calendarIcon clear', close: 'calendarIcon close' } }); } function getDisponibilidade(startDate, endDate, targetDiv) { if (endDate.isSameOrBefore(startDate, 'day month year')) { $("#" + targetDiv + " .fim").popover('show'); } else $("#" + targetDiv + " .fim").popover('hide'); //console.log(moment.duration(endDate.diff(startDate)).as('days')); var duration = Math.round(moment.duration(endDate.diff(startDate)).as('days')); if (duration <= 0) { $("#" + targetDiv + " .dias").replaceWith('<span class="dias">0 days</span>'); } else if (duration > 1) { $("#" + targetDiv + " .dias").replaceWith('<span class="dias">' + duration + ' days</span>'); } else $("#" + targetDiv + " .dias").replaceWith('<span class="dias">' + duration + ' day</span>'); //console.log(duration); return duration } $(document).ready(function() { initDatePickers("inicio0", "fim0"); var startDate = $("#inicio0").data("DateTimePicker").date(); var endDate = $("#fim0").data("DateTimePicker").date(); getDisponibilidade(startDate, endDate, "dispRow0") }); $("input.dispDtp").on("dp.hide", function(event) { if (event.target.id.match(/inicio\\d/)) { var startDateInpt = event.target.id; var endDateInpt = $(this).parent().siblings().children("input[id^='fim']")[0].id; /* console.log(event); console.log($(this)); */ } else { var startDateInpt = $(this).parent().siblings().children("input[id^='inicio']")[0].id; var endDateInpt = event.target.id; } var targetDiv = $(this).parents("div[id^='dispRow']")[0].attributes[1].value; /* console.log(startDateInpt); console.log(endDateInpt); */ var startDate = $("#" + targetDiv + " #" + startDateInpt).data("DateTimePicker").date(); var endDate = $("#" + targetDiv + " #" + endDateInpt).data("DateTimePicker").date(); getDisponibilidade(startDate, endDate, targetDiv); }); $(".addDisp button").click(function(event) { $("#dispRow0").clone(true,true).appendTo(".disp").prop("id", "newDisp"); var sibLength = $("#dispRow0").siblings().length; $("#newDisp div[id^='dispDtpDivInicio']").attr("class", "dispDtpDivInicio" + sibLength); $("#newDisp input[id^='inicio']").attr("name", "dataInicio" + sibLength).prop("id", "inicio" + sibLength); $("#newDisp div[id^='dispDtpDivFim']").attr("class", "dispDtpDivFim" + sibLength); $("#newDisp input[id^='fim']").attr("name", "dataInicio" + sibLength).prop("id", "fim" + sibLength); $("#newDisp .remDisp button").prop("id", "remDispBtn" + sibLength); destroyPickers(sibLength); updatePickers(sibLength); $("#newDisp").attr("id", "dispRow" + sibLength); // console.log($("#dispRow0").siblings()); }) 
 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.css" /> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script> <div class="row"> <div class="col-12 disp"> <div class="form-row" id="dispRow0"> <div class="formGroup col-2 dispDtpDivInicio0"> <label for="dataInicio0" class=" ">start</label> <input name="dataInicio0" type="text" class="form-control dispDtp" id="inicio0" readonly required style="position:relative;"> </div> <div class="formGroup col-2 dispDtpDivFim0"> <label for=" dataFim0" class=" ">end</label> <input name="dataFim0" type="text " class="form-control dispDtp" id="fim0" readonly required style="position:relative;"> <small class="form-text text-muted "> <span class="dias ">0 days</span> </small> </div> </div> </div> </div> <div class="row "> <div class="col-12 addDisp"> <button type="button"> <h5> Add </h5> </button> </div> </div> 

I've searched, and found a couple of questions, but none work like I need 我搜索了一下,发现了几个问题,但是没有一个能像我需要的那样工作

Question 1 问题1

Question 2 问题2

Edit: JSFiddle if needed: 编辑: JSFiddle如果需要的话:

Take this as a lesson in organization, reusing code, and separation of concerns. 将其作为组织,重用代码和关注点分离方面的课程。

Whenever you are dealing with modular components, you want to isolate them so that they are not dependent on each other. 无论何时使用模块化组件,都希望将它们隔离开,以使它们彼此之间不依赖。 So, first, I would recommend not cloning an initialized object, and not cloning something with events. 因此,首先,我建议不要克隆初始化的对象,也不要克隆带有事件的东西。

So, I have created a "view" template. 因此,我创建了一个“视图”模板。 One particular note, as you are aware, you must match the for and name attributes... I simply use a uuid for this, which will ensure two are never the same. 如您所知,需要特别注意的一点是,您必须匹配forname属性...我只是为此使用uuid,这将确保两个uuid永远不会相同。 Indexing would work fine as you have done, but then you have to keep track of that index. 索引工作可以很好地完成,但是随后您必须跟踪该索引。 Up to you. 由你决定。

The view template is initialized each time someone clicks add, and is initially called once when the document loads. 每次有人单击添加时都会初始化视图模板,并且在文档加载时首先调用一次。

The initialization preps the template, calls the date picker initialization, and adds the event handlers. 初始化为模板做准备,调用日期选择器初始化,并添加事件处理程序。

Hope this helps. 希望这可以帮助。

 var tomorrow = moment().add(1, 'day'); var startOfYearMoment = moment(tomorrow) var endOfYearMoment = moment(tomorrow.add(1, 'year')); function calculateDays($inicio,$fim){ return function(event) { var startDate = $inicio.data("DateTimePicker").date(); var endDate = $fim.data("DateTimePicker").date(); var $span = $fim.parent().find('.dias'); getDisponibilidade(startDate, endDate, $span); }; } function initDatePickers($inicio,$fim) { //, parentInicio, parentFim) { var options = { locale: 'pt', ignoreReadonly: true, focusOnShow: false, viewMode: 'months', format: 'DD/MM/YYYY', // widgetParent: $(parentInicio), widgetPositioning: { horizontal: 'auto', vertical: 'auto' }, icons: { time: 'calendarIcon time', date: 'calendarIcon date', up: 'calendarIcon up', down: 'calendarIcon down', previous: 'calendarIcon prev', next: 'calendarIcon next', today: 'calendarIcon today', clear: 'calendarIcon clear', close: 'calendarIcon close' } }; options.defaultDate = startOfYearMoment, $inicio.datetimepicker(options); options.defaultDate = endOfYearMoment; $fim.datetimepicker(options); var hideHandler = calculateDays($inicio,$fim); $inicio.on("dp.hide",hideHandler); $fim.on("dp.hide",hideHandler); hideHandler(); // run once. } function getDisponibilidade(startDate, endDate, $span) { var duration = Math.round(moment.duration(endDate.diff(startDate)).as('days')); if (duration <= 0) { $span.text("0"); }else{ $span.text(duration); } return duration } $(document).ready(function() { addDateDurationWidget(); // Add an initial date widgit. }); function addDateDurationWidget(){ var $template = $("#view-templates .view").clone() var uu1 = uuid(); var uu2 = uuid(); var replaceUuid = function(uu){ return function(i,s){return s.replace(/{{uuid}}/,uu)} } $template.find('.dispDtpDivInicio label').attr("for",replaceUuid(uu1)) $template.find('.dispDtpDivInicio input').attr("name",replaceUuid(uu1)) $template.find('.dispDtpDivFim label').attr("for",replaceUuid(uu2)) $template.find('.dispDtpDivFim input').attr("name",replaceUuid(uu2)) $template.appendTo(".disp").prop("id", "newDisp"); $inicio = $template.find('input.inicio'); $fim = $template.find('input.fim'); initDatePickers($inicio,$fim); } $(".addDisp button").click(function(event) { addDateDurationWidget(); }) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/node-uuid/1.4.8/uuid.min.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.css" /> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script> <div class="row"> <div class="col-12 disp"> </div> </div> <div class="row "> <div class="col-12 addDisp"> <button type="button"> <h5> Add </h5> </button> </div> </div> <div id="view-templates" style="display:none;"> <div class="form-row view"> <div class="formGroup col-2 dispDtpDivInicio"> <label for="dataInicio-{{uuid}}" class=" ">start</label> <input name="dataInicio-{{uuid}}" type="text" class="form-control inicio dispDtp" readonly required style="position:relative;"> </div> <div class="formGroup col-2 dispDtpDivFim"> <label for="dataFim-{{uuid}}" class=" ">end</label> <input name="dataFim-{{uuid}" type="text " class="form-control fim dispDtp" readonly required style="position:relative;"> <small class="form-text text-muted "> <span class="dias">0</span><span> days</span> </small> </div> </div> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM