PageSourceSearch

https://planovo.de/base/global/vendor/datepair/datepair.js

js planovo.de collected 2026-10-01 23:57:54 UTC 11,506 bytes, 363 lines download raw bytes

1/*!
2 * datepair.js v0.4.15 - A javascript plugin for intelligently selecting date and time ranges inspired by Google Calendar.
3 * Copyright (c) 2016 Jon Thornton - http://jonthornton.github.com/Datepair.js
4 * License: MIT
5 */
6
7(function(window, document) {
8
9	'use strict';
10
11	var _ONE_DAY = 86400000;
12	var jq = window.Zepto || window.jQuery;
13	
14	function simpleExtend(obj1, obj2) {
15		var out = obj2 || {};
16	
17		for (var i in obj1) {
18			if (!(i in out)) {
19				out[i] = obj1[i];
20			}
21		}
22	
23		return out;
24	}
25	
26	// IE's custom event support is totally borked.
27	// Use jQuery if possible
28	function triggerSimpleCustomEvent(el, eventName) {
29		if (jq) {
30			jq(el).trigger(eventName);
31		} else {
32			var event = document.createEvent('CustomEvent');
33			event.initCustomEvent(eventName, true, true, {});
34			el.dispatchEvent(event);
35		}
36	}
37	
38	// el.classList not supported by < IE10
39	// use jQuery if available
40	function hasClass(el, className) {
41		if (jq) {
42			return jq(el).hasClass(className);
43		} else {
44			return el.classList.contains(className);
45		}
46	}
47	
48	function Datepair(container, options) {
49		this.dateDelta = null;
50		this.timeDelta = null;
51		this._defaults =	{
52			startClass: 'start',
53			endClass: 'end',
54			timeClass: 'time',
55			dateClass: 'date',
56			defaultDateDelta: 0,
57			defaultTimeDelta: null,
58			anchor: 'start',
59	
60			// defaults for jquery-timepicker; override when using other input widgets
61			parseTime: function(input){
62				return jq(input).timepicker('getTime');
63			},
64			updateTime: function(input, dateObj){
65				jq(input).timepicker('setTime', dateObj);
66			},
67			setMinTime: function(input, dateObj){
68				jq(input).timepicker('option', 'minTime', dateObj);
69			},
70	
71			// defaults for bootstrap datepicker; override when using other input widgets
72			parseDate: function(input){
73				return input.value && jq(input).datepicker('getDate');
74			},
75			updateDate: function(input, dateObj){
76				jq(input).datepicker('update', dateObj);
77			}
78		};
79	
80		this.container = container;
81		this.settings = simpleExtend(this._defaults, options);
82	
83		this.startDateInput = this.container.querySelector('.'+this.settings.startClass+'.'+this.settings.dateClass);
84		this.endDateInput = this.container.querySelector('.'+this.settings.endClass+'.'+this.settings.dateClass);
85		this.startTimeInput = this.container.querySelector('.'+this.settings.startClass+'.'+this.settings.timeClass);
86		this.endTimeInput = this.container.querySelector('.'+this.settings.endClass+'.'+this.settings.timeClass);
87	
88		// initialize date and time deltas
89		this.refresh();
90	
91		// init starts here
92		this._bindChangeHandler();
93	}
94	
95	Datepair.prototype = {
96		constructor: Datepair,
97	
98		option: function(key, value)
99		{
100			if (typeof key == 'object') {
101				this.settings = simpleExtend(this.settings, key);
102	
103			} else if (typeof key == 'string' && typeof value != 'undefined') {
104				this.settings[key] = value;
105	
106			} else if (typeof key == 'string') {
107				return this.settings[key];
108			}
109	
110			this._updateEndMintime();
111		},
112	
113		getTimeDiff: function()
114		{
115			// due to the fact that times can wrap around, timeDiff for any
116			// time-only pair will always be >= 0
117			var delta = this.dateDelta + this.timeDelta;
118			if (delta < 0 && (!this.startDateInput || !this.endDateInput) ) {
119				delta += _ONE_DAY;
120			}
121	
122			return delta;
123		},
124	
125		refresh: function()
126		{
127			if (this.startDateInput && this.startDateInput.value && this.endDateInput && this.endDateInput.value) {
128				var startDate = this.settings.parseDate(this.startDateInput);
129				var endDate = this.settings.parseDate(this.endDateInput);
130				if (startDate && endDate) {
131					this.dateDelta = endDate.getTime() - startDate.getTime();
132				}
133			}
134			if (this.startTimeInput && this.startTimeInput.value && this.endTimeInput && this.endTimeInput.value) {
135				var startTime = this.settings.parseTime(this.startTimeInput);
136				var endTime = this.settings.parseTime(this.endTimeInput);
137				if (startTime && endTime) {
138					this.timeDelta = endTime.getTime() - startTime.getTime();
139					this._updateEndMintime();
140				}
141			}
142		},
143	
144		remove: function()
145		{
146			this._unbindChangeHandler();
147		},
148	
149		_bindChangeHandler: function(){
150			// addEventListener doesn't work with synthetic "change" events
151			// fired by jQuery's trigger() functioin. If jQuery is present,
152			// use that for event binding
153			if (jq) {
154				jq(this.container).on('change.datepair', jq.proxy(this.handleEvent, this));
155			} else {
156				this.container.addEventListener('change', this, false);
157			}
158		},
159	
160		_unbindChangeHandler: function(){
161			if (jq) {
162				jq(this.container).off('change.datepair');
163			} else {
164				this.container.removeEventListener('change', this, false);
165			}
166		},
167	
168		// This function will be called when passing 'this' to addEventListener
169		handleEvent: function(e){
170			// temporarily unbind the change handler to prevent triggering this
171			// if we update other inputs
172			this._unbindChangeHandler();
173	
174			if (hasClass(e.target, this.settings.dateClass)) {
175				if (e.target.value != '') {
176					this._dateChanged(e.target);
177					this._timeChanged(e.target);
178				} else {
179					this.dateDelta = null;
180				}
181	
182			} else if (hasClass(e.target, this.settings.timeClass)) {
183				if (e.target.value != '') {
184					this._timeChanged(e.target);
185				} else {
186					this.timeDelta = null;
187				}
188			}
189	
190			this._validateRanges();
191			this._updateEndMintime();
192			this._bindChangeHandler();
193		},
194	
195		_dateChanged: function(target){
196			if (!this.startDateInput || !this.endDateInput) {
197				return;
198			}
199	
200			var startDate = this.settings.parseDate(this.startDateInput);
201			var endDate = this.settings.parseDate(this.endDateInput);
202	
203			if (!startDate || !endDate) {
204				if (this.settings.defaultDateDelta !== null) {
205					if (startDate) {
206						var newEnd = new Date(startDate.getTime() + this.settings.defaultDateDelta * _ONE_DAY);
207						this.settings.updateDate(this.endDateInput, newEnd);
208	
209					} else if (endDate) {
210						var newStart = new Date(endDate.getTime() - this.settings.defaultDateDelta * _ONE_DAY);
211						this.settings.updateDate(this.startDateInput, newStart);
212					}
213	
214					this.dateDelta = this.settings.defaultDateDelta * _ONE_DAY;
215				} else {
216					this.dateDelta = null;
217				}
218	
219				return;
220			}
221	
222			if (this.settings.anchor == 'start' && hasClass(target, this.settings.startClass)) {
223				var newDate = new Date(startDate.getTime() + this.dateDelta);
224				this.settings.updateDate(this.endDateInput, newDate);
225			} else if (this.settings.anchor == 'end' && hasClass(target, this.settings.endClass)) {
226				var newDate = new Date(endDate.getTime() - this.dateDelta);
227				this.settings.updateDate(this.startDateInput, newDate);
228			} else {
229				if (endDate < startDate) {
230					var otherInput = hasClass(target, this.settings.startClass) ? this.endDateInput : this.startDateInput;
231					var selectedDate = this.settings.parseDate(target);
232					this.dateDelta = 0;
233					this.settings.updateDate(otherInput, selectedDate);
234				} else {
235					this.dateDelta = endDate.getTime() - startDate.getTime();
236				}
237			}
238		},
239	
240		_timeChanged: function(target){
241			if (!this.startTimeInput || !this.endTimeInput) {
242				return;
243			}
244	
245			var startTime = this.settings.parseTime(this.startTimeInput);
246			var endTime = this.settings.parseTime(this.endTimeInput);
247	
248			if (!startTime || !endTime) {
249				if (this.settings.defaultTimeDelta !== null) {
250					if (startTime) {
251						var newEnd = new Date(startTime.getTime() + this.settings.defaultTimeDelta);
252						this.settings.updateTime(this.endTimeInput, newEnd);
253					} else if (endTime) {
254						var newStart = new Date(endTime.getTime() - this.settings.defaultTimeDelta);
255						this.settings.updateTime(this.startTimeInput, newStart);
256					}
257	
258					this.timeDelta = this.settings.defaultTimeDelta;
259				} else {
260					this.timeDelta = null;
261				}
262	
263				return;
264			}
265	
266			if (this.settings.anchor == 'start' && hasClass(target, this.settings.startClass)) {
267				if(this.settings.defaultTimeDelta !== null){
268					var newTime = new Date(startTime.getTime() + this.timeDelta);
269					this.settings.updateTime(this.endTimeInput, newTime);
270					endTime = this.settings.parseTime(this.endTimeInput);
271					
272					this._doMidnightRollover(startTime, endTime);
273				}
274			} else if (this.settings.anchor == 'end' && hasClass(target, this.settings.endClass)) {
275				var newTime = new Date(endTime.getTime() - this.timeDelta);
276				this.settings.updateTime(this.startTimeInput, newTime);
277				startTime = this.settings.parseTime(this.startTimeInput);
278	
279				this._doMidnightRollover(startTime, endTime);
280			} else {
281				this._doMidnightRollover(startTime, endTime);
282	
283				var startDate, endDate;
284				if (this.startDateInput && this.endDateInput) {
285					startDate = this.settings.parseDate(this.startDateInput);
286					endDate = this.settings.parseDate(this.endDateInput);
287				}
288	
289				if ((+startDate == +endDate) && (endTime < startTime)) {
290					var thisInput  = hasClass(target, this.settings.endClass) ? this.endTimeInput : this.startTimeInput;
291					var otherInput = hasClass(target, this.settings.startClass) ? this.endTimeInput : this.startTimeInput;
292					var selectedTime = this.settings.parseTime(thisInput);
293					this.timeDelta = 0;
294					this.settings.updateTime(otherInput, selectedTime);
295				} else {
296					this.timeDelta = endTime.getTime() - startTime.getTime();
297				}
298			}
299	
300	
301		},
302	
303		_doMidnightRollover: function(startTime, endTime) {
304			if (!this.startDateInput || !this.endDateInput) {
305				return;
306			}
307	
308			var endDate = this.settings.parseDate(this.endDateInput);
309			var startDate = this.settings.parseDate(this.startDateInput);
310			var newDelta = endTime.getTime() - startTime.getTime();
311			var offset = (endTime < startTime) ? _ONE_DAY : -1 * _ONE_DAY;
312	
313			if (this.dateDelta !== null
314					&& this.dateDelta + this.timeDelta <= _ONE_DAY
315					&& this.dateDelta + newDelta != 0
316					&& (offset > 0 || this.dateDelta != 0)
317					&& ((newDelta >= 0 && this.timeDelta < 0) || (newDelta < 0 && this.timeDelta >= 0))) {
318	
319				if (this.settings.anchor == 'start') {
320					this.settings.updateDate(this.endDateInput, new Date(endDate.getTime() + offset));
321					this._dateChanged(this.endDateInput);
322				} else if (this.settings.anchor == 'end') {
323					this.settings.updateDate(this.startDateInput, new Date(startDate.getTime() - offset));
324					this._dateChanged(this.startDateInput);
325				}
326			}
327			this.timeDelta = newDelta;
328		},
329	
330		_updateEndMintime: function(){
331			if (typeof this.settings.setMinTime != 'function') return;
332	
333			var baseTime = null;
334			if (this.settings.anchor == 'start' && (!this.dateDelta || this.dateDelta < _ONE_DAY || (this.timeDelta && this.dateDelta + this.timeDelta < _ONE_DAY))) {
335				baseTime = this.settings.parseTime(this.startTimeInput);
336			}
337	
338			this.settings.setMinTime(this.endTimeInput, baseTime);
339		},
340	
341		_validateRanges: function(){
342			if (this.startTimeInput && this.endTimeInput && this.timeDelta === null) {
343				triggerSimpleCustomEvent(this.container, 'rangeIncomplete');
344				return;
345			}
346	
347			if (this.startDateInput && this.endDateInput && this.dateDelta === null) {
348				triggerSimpleCustomEvent(this.container, 'rangeIncomplete');
349				return;
350			}
351	
352			// due to the fact that times can wrap around, any time-only pair will be considered valid
353			if (!this.startDateInput || !this.endDateInput || this.dateDelta + this.timeDelta >= 0) {
354				triggerSimpleCustomEvent(this.container, 'rangeSelected');
355			} else {
356				triggerSimpleCustomEvent(this.container, 'rangeError');
357			}
358		}
359	};
360
361	window.Datepair = Datepair;
362
363}(window, document));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.