(function (){
'use strict';
var LOCALES={
nl: {
months: ['januari','februari','maart','april','mei','juni','juli','augustus','september','oktober','november','december'],
weekdays: ['ma','di','wo','do','vr','za','zo'],
weekStart: 1,
placeholder: 'Zoek op datum',
arrival: 'Aankomst',
departure: 'Vertrek',
apply: 'Toepassen',
reset: 'Wis',
prevMonth: 'Vorige maand',
nextMonth: 'Volgende maand',
needDeparture: 'Tik nu ook een vertrekdatum aan',
},
en: {
months: ['January','February','March','April','May','June','July','August','September','October','November','December'],
weekdays: ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'],
weekStart: 1,
placeholder: 'Search by date',
arrival: 'Arrival',
departure: 'Departure',
apply: 'Apply',
reset: 'Clear',
prevMonth: 'Previous month',
nextMonth: 'Next month',
needDeparture: 'Now tap a departure date',
},
de: {
months: ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'],
weekdays: ['Mo','Di','Mi','Do','Fr','Sa','So'],
weekStart: 1,
placeholder: 'Nach Datum suchen',
arrival: 'Anreise',
departure: 'Abreise',
apply: 'Anwenden',
reset: 'Löschen',
prevMonth: 'Vorheriger Monat',
nextMonth: 'Nächster Monat',
needDeparture: 'Bitte noch ein Abreisedatum auswählen',
},
es: {
months: ['enero','febrero','marzo','abril','mayo','junio','julio','agosto','septiembre','octubre','noviembre','diciembre'],
weekdays: ['lu','ma','mi','ju','vi','sá','do'],
weekStart: 1,
placeholder: 'Buscar por fecha',
arrival: 'Llegada',
departure: 'Salida',
apply: 'Aplicar',
reset: 'Borrar',
prevMonth: 'Mes anterior',
nextMonth: 'Mes siguiente',
needDeparture: 'Toca ahora una fecha de salida',
},
};
function pad2(n){ return n < 10 ? '0' + n:'' + n; }
function fmtISO(d){
return d.getFullYear() + '-' + pad2(d.getMonth() + 1) + '-' + pad2(d.getDate());
}
function parseISO(s){
if(!s||!/^\d{4}-\d{2}-\d{2}$/.test(s)) return null;
var p=s.split('-').map(Number);
var d=new Date(p[0], p[1] - 1, p[2]);
return isNaN(d.getTime()) ? null:d;
}
function startOfDay(d){
var c=new Date(d.getTime());
c.setHours(0, 0, 0, 0);
return c;
}
function addDays(d, n){
var c=new Date(d.getTime());
c.setDate(c.getDate() + n);
return c;
}
function addMonths(d, n){
return new Date(d.getFullYear(), d.getMonth() + n, 1);
}
function sameDay(a, b){
return a&&b && a.getFullYear()===b.getFullYear()
&& a.getMonth()===b.getMonth()&&a.getDate()===b.getDate();
}
function urlParam(){
try {
var params=new URLSearchParams(window.location.search);
for (var i=0; i < arguments.length; i++){
var v=params.get(arguments[i]);
if(v) return v;
}} catch (e){}
return '';
}
function fmtShort(d, locale){
var L=LOCALES[locale]||LOCALES.nl;
return d.getDate() + ' ' + L.months[d.getMonth()].slice(0, 3) + ' ' + d.getFullYear();
}
function fmtShortCompact(d, locale){
var L=LOCALES[locale]||LOCALES.nl;
return d.getDate() + ' ' + L.months[d.getMonth()].slice(0, 3);
}
function AeDatePicker(root, opts){
this.root=root;
this.opts=Object.assign({
locale: 'nl',
defaultFromOffsetMonths: 2,
defaultRange: 7,
minDate: startOfDay(new Date()),
maxDate: null,
monthsDesktop: 2,
monthsMobile: 1,
compact: root.classList.contains('ae-datepicker--compact'),
}, opts||{});
this.fromInput=root.querySelector('[data-aedp-from]');
this.toInput=root.querySelector('[data-aedp-to]');
this.trigger=root.querySelector('[data-aedp-trigger]');
this.popover=root.querySelector('[data-aedp-popover]');
this.fromDisplay=root.querySelector('[data-aedp-display-from]');
this.toDisplay=root.querySelector('[data-aedp-display-to]');
this.L=LOCALES[this.opts.locale]||LOCALES.nl;
this.from=null;
this.to=null;
this.hoverDate=null;
this.pendingFrom=null;
this.viewMonth=null;
this.isOpen=false;
if(!this.fromInput||!this.toInput||!this.trigger||!this.popover){
return;
}
this._init();
}
AeDatePicker.prototype._init=function (){
var self=this;
var initFrom=parseISO(this.fromInput.value)||parseISO(urlParam('date_from', 'start_date'));
var initTo=parseISO(this.toInput.value)||parseISO(urlParam('date_to',   'end_date'));
if(initFrom&&initTo&&initTo <=initFrom) initTo=null;
this._setRange(initFrom, initTo);
var anchor=initFrom||new Date();
this.viewMonth=new Date(anchor.getFullYear(), anchor.getMonth(), 1);
var avail=document.getElementById('ae-available-only');
if(avail&&!avail.__aedpFlagBound){
avail.__aedpFlagBound=true;
avail.addEventListener('change', function (){
try { sessionStorage.setItem('ae_avail_user_set', '1'); } catch (e){}});
}
if(initFrom&&initTo&&avail&&!avail.checked){
var userSet=false;
try { userSet=sessionStorage.getItem('ae_avail_user_set')==='1'; } catch (e){}
if(!userSet){
avail.checked=true;
avail.dispatchEvent(new Event('change', { bubbles: true }));
}}
this.trigger.addEventListener('click', function (e){
e.preventDefault();
self.isOpen ? self.close():self.open();
});
this.popover.addEventListener('mouseover', function (e){
var btn=e.target.closest('[data-aedp-day]');
if(!btn||!self.pendingFrom) return;
var d=parseISO(btn.getAttribute('data-aedp-day'));
if(sameDay(d, self.hoverDate)) return;
self.hoverDate=d;
self._updateRangePreview();
});
this.popover.addEventListener('mouseleave', function (){
if(self.pendingFrom&&self.hoverDate){
self.hoverDate=null;
self._updateRangePreview();
}});
document.addEventListener('click', function (e){
if(!self.isOpen) return;
if(self.root.contains(e.target))     return;
if(self.popover.contains(e.target))  return;
self.close();
});
document.addEventListener('keydown', function (e){
if(self.isOpen&&e.key==='Escape'){
self.close();
self.trigger.focus();
}});
window.addEventListener('resize', this._debounced(function (){
if(self.isOpen) self._renderMonths();
}, 150));
};
AeDatePicker.prototype._debounced=function (fn, wait){
var t=null;
return function (){
var args=arguments, self=this;
clearTimeout(t);
t=setTimeout(function (){ fn.apply(self, args); }, wait);
};};
AeDatePicker.prototype._setRange=function (from, to, interactive){
this.from=from ? startOfDay(from):null;
this.to=to   ? startOfDay(to):null;
this.pendingFrom=null;
this.hoverDate=null;
this._syncInputs(!!interactive);
this._renderTrigger();
};
AeDatePicker.prototype._resetRange=function (){
this._setRange(null, null, true);
if(this.isOpen) this._renderMonths();
};
AeDatePicker.prototype._syncInputs=function (interactive){
var changed=false;
var newFrom=this.from ? fmtISO(this.from):'';
var newTo=this.to   ? fmtISO(this.to):'';
if(this.fromInput.value!==newFrom){ this.fromInput.value=newFrom; changed=true; }
if(this.toInput.value!==newTo){ this.toInput.value=newTo;   changed=true; }
if(changed){
this.fromInput.dispatchEvent(new Event('change', { bubbles: true }));
this.toInput.dispatchEvent(new Event('change',   { bubbles: true }));
if(interactive){
var avail=document.getElementById('ae-available-only');
if(avail){
var shouldBeChecked = !!(newFrom&&newTo);
if(avail.checked!==shouldBeChecked){
avail.checked=shouldBeChecked;
avail.dispatchEvent(new Event('change', { bubbles: true }));
}}
}
var availMirror=this.root.querySelector('[data-aedp-avail-mirror]');
if(availMirror){
availMirror.value=(newFrom&&newTo) ? '1':'';
}}
};
AeDatePicker.prototype._renderTrigger=function (){
var empty = !this.from&&!this.to;
var fmt=this.opts.compact ? fmtShortCompact:fmtShort;
this.root.classList.toggle('is-empty', empty);
if(this.fromDisplay){
this.fromDisplay.textContent=empty
? this.L.placeholder
: (this.from ? fmt(this.from, this.opts.locale):this.L.arrival);
this.fromDisplay.classList.toggle('is-empty', !this.from);
}
if(this.toDisplay){
this.toDisplay.textContent=this.to ? fmt(this.to, this.opts.locale):this.L.departure;
this.toDisplay.classList.toggle('is-empty', !this.to);
}};
AeDatePicker.prototype._onDayClick=function (d){
if(!d) return;
if(this.opts.minDate&&d < this.opts.minDate) return;
if(this.opts.maxDate&&d > this.opts.maxDate) return;
var msgEl=this.popover.querySelector('[data-aedp-msg]');
if(msgEl){ msgEl.textContent=''; msgEl.classList.remove('is-error'); }
if(!this.pendingFrom){
this.from=d;
this.to=null;
this.pendingFrom=d;
this.hoverDate=null;
this._syncInputs();
this._renderTrigger();
this._renderMonths();
}else{
if(d <=this.pendingFrom){
this.from=d;
this.to=null;
this.pendingFrom=d;
this.hoverDate=null;
this._syncInputs();
this._renderTrigger();
this._renderMonths();
}else{
this.from=this.pendingFrom;
this.to=d;
this.pendingFrom=null;
this.hoverDate=null;
this._syncInputs(true);
this._renderTrigger();
this._renderMonths();
var self=this;
setTimeout(function (){ self.close(); }, 180);
}}
};
AeDatePicker.prototype.open=function (){
if(this.isOpen) return;
this.isOpen=true;
this.popover.hidden=false;
this.root.classList.add('is-open');
this._origParent=this.popover.parentNode;
this._origNext=this.popover.nextSibling;
document.body.appendChild(this.popover);
document.body.classList.add('aedp-modal-open');
this.trigger.setAttribute('aria-expanded', 'true');
if(this.from){
this.viewMonth=new Date(this.from.getFullYear(), this.from.getMonth(), 1);
}
this._renderMonths();
};
AeDatePicker.prototype.close=function (){
if(!this.isOpen) return;
this.isOpen=false;
this.popover.hidden=true;
this.root.classList.remove('is-open');
if(this._origParent){
this._origParent.insertBefore(this.popover, this._origNext||null);
this._origParent=null;
this._origNext=null;
}
if(!document.querySelector('.ae-datepicker.is-open')){
document.body.classList.remove('aedp-modal-open');
}
this.trigger.setAttribute('aria-expanded', 'false');
if(this.pendingFrom&&!this.to){
this.pendingFrom=null;
this._renderTrigger();
}};
AeDatePicker.prototype._monthsVisible=function (){
return window.matchMedia('(min-width: 720px)').matches
? this.opts.monthsDesktop:this.opts.monthsMobile;
};
AeDatePicker.prototype._renderMonths=function (){
var count=this._monthsVisible();
var parts=[];
parts.push('<div class="aedp-nav">');
parts.push('<button type="button" class="aedp-nav__btn aedp-nav__btn--prev" data-aedp-nav="-1" aria-label="' + this.L.prevMonth + '">&lsaquo;</button>');
parts.push('<div class="aedp-nav__titles">');
for (var i=0; i < count; i++){
var m=addMonths(this.viewMonth, i);
parts.push('<div class="aedp-nav__title">' + this.L.months[m.getMonth()] + ' ' + m.getFullYear() + '</div>');
}
parts.push('</div>');
parts.push('<button type="button" class="aedp-nav__btn aedp-nav__btn--next" data-aedp-nav="1" aria-label="' + this.L.nextMonth + '">&rsaquo;</button>');
parts.push('</div>');
parts.push('<div class="aedp-months">');
for (var j=0; j < count; j++){
parts.push(this._renderMonth(addMonths(this.viewMonth, j)));
}
parts.push('</div>');
parts.push('<div class="aedp-foot">');
parts.push('<div class="aedp-foot__msg" data-aedp-msg></div>');
parts.push('<div class="aedp-foot__btns">');
parts.push('<button type="button" class="aedp-foot__reset" data-aedp-reset>' + this.L.reset + '</button>');
parts.push('<button type="button" class="aedp-foot__apply" data-aedp-apply>' + this.L.apply + '</button>');
parts.push('</div>');
parts.push('</div>');
this.popover.innerHTML=parts.join('');
this._bindCellHandlers();
};
AeDatePicker.prototype._updateRangePreview=function (){
var self=this;
var pf=this.pendingFrom;
var hv=this.hoverDate;
var preview = !!(pf&&hv&&!this.to&&hv > pf);
this.popover.querySelectorAll('[data-aedp-day]').forEach(function (btn){
var iso=btn.getAttribute('data-aedp-day');
var d=parseISO(iso);
var on=preview&&d && d > pf&&d <=hv;
btn.classList.toggle('is-preview', on);
});
};
AeDatePicker.prototype._bindCellHandlers=function (){
var self=this;
var fire=function (handler){
return function (e){
e.preventDefault();
e.stopPropagation();
handler(e);
};};
this.popover.querySelectorAll('[data-aedp-day]').forEach(function (btn){
var iso=btn.getAttribute('data-aedp-day');
btn.addEventListener('click', fire(function (){
self._onDayClick(parseISO(iso));
}));
});
this.popover.querySelectorAll('[data-aedp-nav]').forEach(function (btn){
var dir=parseInt(btn.getAttribute('data-aedp-nav'), 10)||0;
btn.addEventListener('click', fire(function (){
self.viewMonth=addMonths(self.viewMonth, dir);
self._renderMonths();
}));
});
var resetBtn=this.popover.querySelector('[data-aedp-reset]');
if(resetBtn) resetBtn.addEventListener('click', fire(function (){ self._resetRange(); }));
var applyBtn=this.popover.querySelector('[data-aedp-apply]');
if(applyBtn) applyBtn.addEventListener('click', fire(function (){
if(self.pendingFrom&&!self.to){
var msgEl=self.popover.querySelector('[data-aedp-msg]');
if(msgEl){
msgEl.textContent=self.L.needDeparture;
msgEl.classList.add('is-error');
}
return;
}
self.close();
}));
};
AeDatePicker.prototype._renderMonth=function (month){
var self=this;
var y=month.getFullYear(), m=month.getMonth();
var firstDay=new Date(y, m, 1);
var lastDay=new Date(y, m + 1, 0);
var weekStart=this.L.weekStart;
var firstWeekday=(firstDay.getDay() - weekStart + 7) % 7;
var rangeFrom=this.from;
var rangeTo=this.to||(this.pendingFrom&&this.hoverDate&&this.hoverDate > this.pendingFrom ? this.hoverDate:null);
var out=['<div class="aedp-month">'];
out.push('<div class="aedp-month__weekdays">');
for (var w=0; w < 7; w++){
out.push('<div class="aedp-month__wd">' + this.L.weekdays[(weekStart + w) % 7] + '</div>');
}
out.push('</div>');
out.push('<div class="aedp-month__grid">');
for (var p=0; p < firstWeekday; p++) out.push('<div class="aedp-cell aedp-cell--empty"></div>');
for (var d=1; d <=lastDay.getDate(); d++){
var date=new Date(y, m, d);
var iso=fmtISO(date);
var classes=['aedp-cell'];
var disabled=(self.opts.minDate&&date < self.opts.minDate) ||
(self.opts.maxDate&&date > self.opts.maxDate);
if(disabled) classes.push('is-disabled');
if(sameDay(date, rangeFrom)) classes.push('is-from');
if(sameDay(date, this.to))   classes.push('is-to');
if(rangeFrom&&rangeTo&&date > rangeFrom&&date < rangeTo) classes.push('is-in-range');
if(this.pendingFrom&&this.hoverDate&&!this.to
&& date > this.pendingFrom&&date <=this.hoverDate) classes.push('is-preview');
if(disabled){
out.push('<div class="' + classes.join(' ') + '"><span>' + d + '</span></div>');
}else{
out.push('<button type="button" class="' + classes.join(' ') + '" data-aedp-day="' + iso + '"><span>' + d + '</span></button>');
}}
out.push('</div></div>');
return out.join('');
};
window.AeDatePicker=AeDatePicker;
function mountAll(){
var htmlLang=(document.documentElement.lang||'nl').slice(0, 2).toLowerCase();
document.querySelectorAll('.ae-datepicker').forEach(function (root){
if(root.__aedpMounted) return;
root.__aedpMounted=true;
var locale=root.getAttribute('data-aedp-locale')||htmlLang;
new AeDatePicker(root, { locale: locale });
});
}
if(document.readyState==='loading'){
document.addEventListener('DOMContentLoaded', mountAll);
}else{
mountAll();
}})();