(function (){
'use strict';
var DH=window.DiveHubSite=window.DiveHubSite||{};
if(DH.bookReady) return;
DH.bookReady=true;
function $(sel, el){ return (el||document).querySelector(sel); }
function $$(sel, el){ return Array.prototype.slice.call((el||document).querySelectorAll(sel)); }
function h(tag, attrs, kids){
var el=document.createElement(tag);
if(attrs) Object.keys(attrs).forEach(function (k){
var v=attrs[k];
if(v===null||v===undefined||v===false) return;
if(k==='text') el.textContent=v;
else if(k==='class') el.className=v;
else if(k.slice(0, 2)==='on') el.addEventListener(k.slice(2), v);
else el.setAttribute(k, v===true ? '':String(v));
});
(kids||[]).forEach(function (k){ if(k!==null&&k!==undefined&&k!==false) el.appendChild(typeof k==='string' ? document.createTextNode(k):k); });
return el;
}
function clear(el){ while (el&&el.firstChild) el.removeChild(el.firstChild); return el; }
function fmt(s){
var a=arguments, i=0;
return String(s).replace(/%(\d+)\$s|%s/g, function (m, n){ return n ? String(a[+n]):String(a[++i]); });
}
function pad(n){ return (n < 10 ? '0':'') + n; }
function ymd(d){ return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()); }
function parse(s){ var p=String(s).split('-'); return new Date(+p[0], +p[1] - 1, +(p[2]||1)); }
function monthOf(s){ return s ? String(s).slice(0, 7):null; }
function addMonth(m, k){ var d=parse(m + '-01'); d.setMonth(d.getMonth() + k); return ymd(d).slice(0, 7); }
function mins(hm){ var p=String(hm||'').split(':'); return (+p[0]||0) * 60 + (+p[1]||0); }
function hm(m){ m=((m % 1440) + 1440) % 1440; return pad(Math.floor(m / 60)) + ':' + pad(m % 60); }
function urlPick(){
var out={};
try { new URLSearchParams(location.search).forEach(function (v, k){ if(k.indexOf('dhb_')===0) out[k.slice(4)]=v; });} catch (e){}
return out;
}
function source(){
var m=/[?&]utm_source=([^&#]+)/.exec(location.search);
if(m){ try { return decodeURIComponent(m[1].replace(/\+/g, ' ')).slice(0, 60); } catch (e){ return ''; }}
try { if(document.referrer){ var hst=new URL(document.referrer).hostname; if(hst&&hst!==location.hostname) return hst.replace(/^www\./, ''); }} catch (e){}
return '';
}
function Box(el, c){
this.el=el; this.c=c; this.L=c.L; this.root=el.closest ? el.closest('.dh-site'):null;
this.want=urlPick();
this.seq=0;
}
Box.prototype.money=function (v){
v=Math.round(v * 100) / 100;
var n=Math.abs(v - Math.round(v)) < 0.005 ? Math.round(v).toLocaleString('en-US'):v.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
return n + ' ' + this.c.cur;
};
Box.prototype.whole=function (v){ return Math.round(v).toLocaleString('en-US'); };
Box.prototype.count=function (key, n){
var f=(this.c.pl||{})[key]||['%d', '%d', '%d', '%d'], k=n===1 ? 0:n===2 ? 1:(n % 100 >=3&&n % 100 <=10) ? 2:3;
return String(f[k]).replace('%d', String(n));
};
Box.prototype.comma=function (){ return this.c.lang==='ar' ? '، ':', '; };
Box.prototype.offerPrice=function (p){ return this.c.offer&&this.c.offer.pct > 0 ? Math.round(p * (1 - this.c.offer.pct / 100)):p; };
Box.prototype.time=function (t){
var m=mins(t), hh=Math.floor(m / 60) % 24, ap=hh < 12 ? this.c.cal.am:this.c.cal.pm;
return (((hh + 11) % 12) + 1) + ':' + pad(m % 60) + ' ' + ap;
};
Box.prototype.day=function (s, short){
var d=parse(s), w=this.c.cal, ar=this.c.lang==='ar';
if(short&&!ar) return w.short[d.getDay()] + ' ' + d.getDate() + ' ' + w.monthsShort[d.getMonth()];
return w.days[d.getDay()] + ' ' + d.getDate() + ' ' + w.months[d.getMonth()];
};
Box.prototype.monthName=function (m){ var d=parse(m + '-01'); return this.c.cal.months[d.getMonth()] + ' ' + d.getFullYear(); };
Box.prototype.ts=function (date, t){
var d=parse(date), m=mins(t);
return Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), Math.floor(m / 60), m % 60) / 1000 - (this.c.tz||3) * 3600;
};
Box.prototype.now=function (){ return Date.now() / 1000; };
Box.prototype.api=function (path, params, post){
var c=this.c, q=new URLSearchParams();
Object.keys(params||{}).forEach(function (k){
var v=params[k];
if(v===null||v===undefined) return;
if(typeof v==='object') Object.keys(v).forEach(function (kk){ if(v[kk]) q.append(k + '[' + kk + ']', String(v[kk])); });
else q.set(k, String(v));
});
q.set('lang', c.lang);
if(c.preview){ q.set('preview', '1'); if(c.draft) q.set('draft', '1'); }
var url=c.api + '/' + path, opt={ credentials: c.preview ? 'same-origin':'omit', mode: 'cors' };
if(post){ opt.method='POST'; opt.body=q; } else url +='?' + q.toString();
return fetch(url, opt).then(function (r){ return r.json().catch(function (){ return { ok: false };});});
};
Box.prototype.error=function (msg){
var e=$('[data-dhb-err]', this.el);
if(!e) return;
e.textContent=msg||''; e.hidden = !msg;
};
Box.prototype.used=function (){
if(this.counted) return;
this.counted=true;
try {
if(DH.event) DH.event('box', this.c.exp, this.root);
else if(!this.c.preview&&window.fetch){
var b=new URLSearchParams(); b.set('e', 'box'); b.set('x', String(this.c.exp)); var s=source(); if(s) b.set('src', s);
fetch(this.c.api + '/event', { method: 'POST', body: b, mode: 'cors', credentials: 'omit' }).then(function (r){ return r.text(); }).catch(function (){});
}} catch (e){}};
Box.prototype.bar=function (price, sub){
if(!this.root) return;
var p=$('[data-dh-bar-price]', this.root), s=$('[data-dh-bar-sub]', this.root);
if(p&&price){ p.textContent=price; p.classList.remove('is-name'); }
if(s&&sub!==undefined) s.textContent=sub;
};
Box.prototype.stepper=function (label, sub, n, min, max, onChange, unit, cls){
var L=this.L, self=this;
var less=h('button', { type: 'button', 'class': 'dhb-pm', 'aria-label': fmt(L.less, unit||label), disabled: n <=min, onclick: function (){ self.used(); onChange(Math.max(min, n - 1)); }}, ['−']);
var more=h('button', { type: 'button', 'class': 'dhb-pm', 'aria-label': fmt(L.more, unit||label), disabled: n >=max, onclick: function (){ self.used(); onChange(Math.min(max, n + 1)); }}, ['+']);
return h('div', { 'class': 'dhb-step ' + (cls||'') }, [
h('div', { 'class': 'dhb-step-l' }, [h('div', { 'class': 'dhb-step-name', text: label }), sub ? h('div', { 'class': 'dhb-step-sub', text: sub }):null]),
less, h('span', { 'class': 'dhb-n', 'aria-live': 'polite', text: String(n) }), more]);
};
Box.prototype.notice=function (x, startTs){
var L=this.L;
if(!x.notice) return ['', true];
if(!startTs) return [fmt(L.noticePick, x.notice), false];
var cut=startTs - x.notice * 3600, now=this.now();
if(now < cut){
var d=new Date((cut + (this.c.tz||3) * 3600) * 1000), date=d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate());
return [fmt(L.notice, x.notice, this.day(date, true) + this.comma() + this.time(pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()))), true];
}
var left=Math.floor((startTs - now) / 3600);
return [fmt(L.noticeLate, x.notice, left >=1 ? this.count('hours', left):(this.c.pl||{}).lessHour||'1'), false];
};
Box.prototype.drawCal=function (month, cells, pick){
var self=this, c=this.c, cal=$('[data-dhb-cal]', this.el), strip=$('[data-dhb-strip]', this.el);
var mEl=$('[data-dhb-month]', this.el);
if(mEl) mEl.textContent=this.monthName(month);
var prev=$('[data-dhb-prev]', this.el), next=$('[data-dhb-next]', this.el);
if(prev) prev.disabled=month <=monthOf(c.today);
if(next) next.disabled=month >=monthOf(c.last);
clear(cal); clear(strip);
var head=h('div', { 'class': 'dhb-wd', 'aria-hidden': 'true' }, c.cal.mini.map(function (w){ return h('span', { text: w });}));
var grid=h('div', { 'class': 'dhb-grid', role: 'group', 'aria-label': this.monthName(month) });
var first=parse(month + '-01'), lastDay=new Date(first.getFullYear(), first.getMonth() + 1, 0).getDate();
for (var i=0; i < first.getDay(); i++) grid.appendChild(h('span', { 'class': 'dhb-blank' }));
var stripN=0;
for (var d=1; d <=lastDay; d++){
(function (date, n){
var x=cells[date]||{ off: true };
var btn=h('button', { type: 'button', 'class': 'dhb-day' + (x.on ? ' is-on':'') + (x.off ? ' is-off':'') + (x.cls ? ' ' + x.cls:''), disabled: !!x.off, 'data-date': date,
'aria-pressed': x.on ? 'true':'false', 'aria-label': self.day(date) + (x.aria ? ', ' + x.aria:''),
onclick: function (){ if(!x.off){ self.used(); pick(date); }} },
[h('span', { 'class': 'dhb-dn', text: String(n) }), h('span', { 'class': 'dhb-ds', text: x.sub||'' })]);
grid.appendChild(btn);
if(!x.off&&strip){
stripN++;
strip.appendChild(h('button', { type: 'button', 'class': 'dhb-sday' + (x.on ? ' is-on':'') + (x.cls ? ' ' + x.cls:''), 'aria-pressed': x.on ? 'true':'false', 'data-date': date,
'aria-label': self.day(date) + (x.aria ? ', ' + x.aria:''), onclick: function (){ self.used(); pick(date); }},
[h('span', { 'class': 'dhb-sw', text: c.cal.short[parse(date).getDay()] }), h('b', { text: String(n) }), h('span', { 'class': 'dhb-ds', text: x.sub||x.free||'' })]));
}})(month + '-' + pad(d), d);
}
cal.appendChild(head); cal.appendChild(grid);
if(strip){
if(!stripN) strip.appendChild(h('span', { 'class': 'dhb-muted dhb-small', text: this.L.noDays }));
}};
Box.prototype.wire=function (){
var self=this, el=this.el;
var prev=$('[data-dhb-prev]', el), next=$('[data-dhb-next]', el), tog=$('[data-dhb-caltoggle]', el), go=$('[data-dhb-go]', el);
if(prev) prev.addEventListener('click', function (){ self.used(); self.loadMonth(addMonth(self.s.month, -1), false); });
if(next) next.addEventListener('click', function (){ self.used(); self.loadMonth(addMonth(self.s.month, 1), false); });
if(tog) tog.addEventListener('click', function (){
var open = !el.classList.contains('is-calopen');
el.classList.toggle('is-calopen', open);
tog.textContent=open ? self.L.lessCal:self.L.fullCal;
});
if(go) go.addEventListener('click', function (){ self.used(); self.book(); });
};
Box.prototype.hold=function (params){
var self=this, go=$('[data-dhb-go]', this.el), label=go ? go.textContent:'';
if(this.holding) return;
this.holding=true; this.error('');
if(go){ go.disabled=true; go.textContent=this.L.wait; }
var s=source(); if(s) params.src=s;
this.api('hold', params, true).then(function (j){
if(j&&j.ok&&j.checkout){ location.href=j.checkout; return; }
self.holding=false;
if(go){ go.disabled=false; go.textContent=label; }
self.error((j&&j.error)||self.L.error);
if(self.afterError) self.afterError();
}).catch(function (){
self.holding=false;
if(go){ go.disabled=false; go.textContent=label; }
self.error(self.L.error);
});
};
function Shared(el, c){
Box.call(this, el, c);
var w=this.want, opt=null;
c.opts.forEach(function (o){ if(String(o.id)===w.o) opt=o; });
if(w.o&&!opt) this.want=w = {};
this.s={ opt: opt||c.opts[0]||null, month: null, days: {}, date: null, times: [], dep: null, adults: 2, children: 0, infants: 0, x: {}};
if(!this.s.opt){ this.error(this.L.noDaysAll); var g=$('[data-dhb-go]', el); if(g) g.hidden=true; return; }
if(w.a) this.s.adults=Math.max(1, +w.a||1);
if(w.c&&this.s.opt.child) this.s.children=Math.max(0, +w.c||0);
if(w.i&&this.s.opt.infant) this.s.infants=Math.max(0, +w.i||0);
this.s.adults=Math.min(this.s.adults, this.s.opt.max);
this.wire();
this.drawOpts();
this.loadMonth(monthOf(w.date)||monthOf(c.today), true);
}
Shared.prototype=Object.create(Box.prototype);
Shared.prototype.drawOpts=function (){
var self=this, box=$('[data-dhb-opts]', this.el);
if(!box) return;
clear(box);
this.c.opts.forEach(function (o){
var on=self.s.opt&&o.id===self.s.opt.id;
box.appendChild(h('button', { type: 'button', role: 'radio', 'aria-checked': on ? 'true':'false', 'class': 'dhb-len' + (on ? ' is-on':''),
onclick: function (){ if(on) return; self.used(); self.s.opt=o; self.s.children=o.child ? self.s.children:0; self.s.infants=o.infant ? self.s.infants:0; self.s.adults=Math.min(self.s.adults, o.max); self.s.dep=null; self.drawOpts(); self.loadMonth(self.s.month, true); }},
[h('span', { 'class': 'dhb-len-l' }, [h('b', { text: o.name }), o.note ? h('span', { 'class': 'dhb-small', text: o.note }):null]),
h('b', { text: self.money(self.offerPrice(o.price)) })]));
});
};
Shared.prototype.loadMonth=function (month, seek, tries){
var self=this, c=this.c, n=++this.seq;
if(month < monthOf(c.today)) month=monthOf(c.today);
this.s.month=month;
this.api('days', { o: this.s.opt.id, month: month }).then(function (j){
if(n!==self.seq) return;
if(!j||!j.ok){ self.error((j&&j.error)||self.L.error); self.drawCal(month, {}, function (){});return; }
var days={}, any=false;
(j.days||[]).forEach(function (d){ days[d.date]=d; if(!d.full) any=true; });
self.s.days=days;
if(seek&&!any&&month < monthOf(c.last)&&(tries||0) < 4){ self.loadMonth(addMonth(month, 1), true, (tries||0) + 1); return; }
if(seek&&!any) self.error(self.L.noDaysAll);
var want=self.want.date;
var date=self.s.date&&days[self.s.date]&&!days[self.s.date].full ? self.s.date:null;
if(!date&&want&&days[want]&&!days[want].full) date=want;
if(!date&&seek) Object.keys(days).sort().some(function (k){ if(!days[k].full){ date=k; return true; } return false; });
self.drawDays();
if(date) self.pickDay(date); else if(seek){ self.s.date=null; self.s.times=[]; self.s.dep=null; self.drawTimes(); self.drawRest(); }});
};
Shared.prototype.drawDays=function (){
var self=this, cells={}, L=this.L;
Object.keys(this.s.days).forEach(function (k){
var d=self.s.days[k];
cells[k]=d.full ? { off: true, cls: 'is-full', sub: '', aria: L.full }
: { on: k===self.s.date, sub: (d.few ? '● ':'') + self.whole(d.price), aria: self.money(d.price) + (d.few ? ', ' + L.fewLeft:''), cls: d.few ? 'is-few':'' };});
this.drawCal(this.s.month, cells, function (date){ self.pickDay(date); });
};
Shared.prototype.pickDay=function (date){
var self=this, n=++this.seq;
this.s.date=date; this.drawDays();
this.error('');
this.api('times', { o: this.s.opt.id, date: date }).then(function (j){
if(n!==self.seq) return;
self.s.times=(j&&j.ok&&j.times)||[];
var dep=null, want=+self.want.dep||0;
self.s.times.forEach(function (t){ if(t.dep===(self.s.dep||want)) dep=t; });
if(!dep) dep=self.s.times[0]||null;
self.s.dep=dep ? dep.dep:null;
self.want.dep=null;
if(!self.s.times.length&&j && !j.ok) self.error(j.error||self.L.error);
self.drawTimes(); self.drawRest();
});
};
Shared.prototype.cur=function (){
var s=this.s, out=null;
s.times.forEach(function (t){ if(t.dep===s.dep) out=t; });
return out;
};
Shared.prototype.drawTimes=function (){
var self=this, L=this.L, box=$('[data-dhb-times]', this.el);
clear(box);
if(!this.s.date){ box.appendChild(h('span', { 'class': 'dhb-muted', text: L.pickDay })); return; }
if(!this.s.times.length){ box.appendChild(h('span', { 'class': 'dhb-muted', text: L.noDays })); return; }
var prices={}; this.s.times.forEach(function (t){ prices[t.price]=1; });
var many=Object.keys(prices).length > 1;
this.s.times.forEach(function (t){
var on=t.dep===self.s.dep, sub=[];
if(t.checkin&&t.checkin.place) sub.push(t.checkin.time&&t.checkin.time!==t.time ? fmt(L.checkinTimeAt, self.time(t.checkin.time), t.checkin.place):fmt(L.checkinAt, t.checkin.place));
if(t.left===1) sub.push(L.seat1); else if(t.few) sub.push(fmt(L.seatsLeft, t.left)); else if(t.left <=20) sub.push(fmt(L.seats, t.left));
if(many) sub.push(self.money(t.price));
box.appendChild(h('button', { type: 'button', 'class': 'dhb-time' + (on ? ' is-on':'') + (t.few ? ' is-few':''), 'aria-pressed': on ? 'true':'false',
onclick: function (){ self.used(); self.s.dep=t.dep; self.drawTimes(); self.drawRest(); }},
[h('b', { text: t.time ? self.time(t.time):self.day(self.s.date) }), sub.length ? h('span', { 'class': 'dhb-time-sub', text: sub.join(' · ') }):null]));
});
};
Shared.prototype.limits=function (){
var t=this.cur(), max=this.s.opt.max;
if(t&&!this.s.opt.charter) max=Math.min(max, t.left);
return Math.max(1, max);
};
Shared.prototype.drawRest=function (){
var self=this, s=this.s, L=this.L, c=this.c, t=this.cur(), max=this.limits();
if(!s.opt.infant) s.infants=0;
if(s.adults + s.children + s.infants > max){
s.infants=Math.max(0, Math.min(s.infants, max - 1)); s.children=Math.max(0, Math.min(s.children, max - 1 - s.infants)); s.adults=Math.max(1, Math.min(s.adults, max - s.children - s.infants));
}
var unit=t ? t.price:this.offerPrice(s.opt.price), child=t&&t.child_price!==null ? t.child_price:(s.opt.childPrice!==null ? this.offerPrice(s.opt.childPrice):null);
var inf=t&&t.infant_price!=null ? t.infant_price:this.offerPrice(s.opt.infantPrice||0);
var g=clear($('[data-dhb-guests]', this.el));
g.appendChild(this.stepper(L.adults, s.opt.charter ? '':this.money(unit), s.adults, 1, max - s.children - s.infants, function (n){ s.adults=n; self.drawRest(); }, L.adults));
if(s.opt.child){
var cl=c.childAges ? fmt(L.children, c.childAges[0], c.childAges[1]):L.childrenPlain;
g.appendChild(this.stepper(cl, child!==null ? this.money(child):'', s.children, 0, max - s.adults - s.infants, function (n){ s.children=n; self.drawRest(); }, cl));
}
if(s.opt.infant&&c.infantAge > 0){
var il=fmt(L.infants, c.infantAge);
g.appendChild(this.stepper(il, inf > 0 ? this.money(inf):L.free, s.infants, 0, max - s.adults - s.children, function (n){ s.infants=n; self.drawRest(); }, il, 'dhb-step-inf'));
}
var guests=s.adults + s.children, startTs=t&&t.time ? this.ts(s.date, t.time):(s.date ? this.ts(s.date, '00:00'):0);
var ex=$('[data-dhb-extras]', this.el), sec=$('[data-dhb-extsec]', this.el);
clear(ex);
sec.hidden = !c.extras.length;
c.extras.forEach(function (x){
var nt=self.notice(x, t ? startTs:0), late = !nt[1];
if(late) delete s.x[x.id];
var priceTxt=self.money(x.price) + (x.kind==='per_person'||x.basis==='person' ? ' · ' + L.perPersonShort:'');
if(x.kind==='per_person'){
var mx=Math.min(guests, x.max||guests);
if((s.x[x.id]||0) > mx) s.x[x.id]=mx;
ex.appendChild(self.stepper(x.name, [x.desc, priceTxt].filter(Boolean).join(' · '), s.x[x.id]||0, 0, late ? 0:mx, function (n){ s.x[x.id]=n; self.drawRest(); }, x.name));
if(nt[0]) ex.appendChild(h('div', { 'class': 'dhb-notice ' + (late ? 'is-late':'is-ok'), text: nt[0] }));
return;
}
var inc=x.includes&&x.includes.length ? x.includes.join(self.comma()):'';
ex.appendChild(h('label', { 'class': 'dhb-tick' + (late ? ' is-late':'') }, [
h('input', { type: 'checkbox', checked: !!s.x[x.id], disabled: late, onchange: function (ev){ self.used(); if(ev.target.checked) s.x[x.id]=1; else delete s.x[x.id]; self.drawRest(); }}),
h('span', {}, [h('span', { text: x.name }), h('span', { 'class': 'dhb-muted dhb-small', text: ' · ' + [inc||x.desc, priceTxt].filter(Boolean).join(' · ') }),
nt[0] ? h('span', { 'class': 'dhb-notice ' + (late ? 'is-late':'is-ok'), text: nt[0] }):null])]));
});
var sum=clear($('[data-dhb-sum]', this.el)), total=0, lines=[];
if(t){
var aTot=s.opt.charter ? unit:unit * s.adults;
lines.push([fmt(L.adultsLine, this.guestsText(s.adults, 'a'), this.money(unit)), aTot]);
if(s.children&&!s.opt.charter) lines.push([fmt(L.adultsLine, this.guestsText(s.children, 'c'), this.money(child)), child * s.children]);
if(s.infants&&!s.opt.charter) lines.push([inf > 0 ? fmt(L.adultsLine, this.guestsText(s.infants, 'i'), this.money(inf)):fmt(L.infantsFree, this.guestsText(s.infants, 'i')), inf * s.infants]);
c.extras.forEach(function (x){
var q=s.x[x.id]||0;
if(!q) return;
var amt=x.kind==='per_person' ? x.price * q:(x.basis==='person' ? x.price * guests:x.price);
lines.push([(q > 1 ? q + ' × ':'') + x.name, amt]);
});
lines.forEach(function (l){ total +=l[1]; });
sum.appendChild(h('div', { 'class': 'dhb-sum-when', text: this.day(s.date) + (t.time ? ' · ' + this.time(t.time):'') }));
lines.forEach(function (l){ sum.appendChild(h('div', { 'class': 'dhb-line' }, [h('span', { text: l[0] }), h('span', { text: self.money(l[1]) })])); });
sum.appendChild(h('div', { 'class': 'dhb-total' }, [h('b', { text: L.total }), h('span', { text: this.money(total) })]));
var and=this.c.lang==='ar' ? ' و':', ';
this.bar(this.money(total), [this.guestsText(s.adults, 'a') + (s.children ? and + this.guestsText(s.children, 'c'):'') + (s.infants ? and + this.guestsText(s.infants, 'i'):''), this.day(s.date, true), t.time ? this.time(t.time):''].filter(Boolean).join(' · '));
}else{
sum.appendChild(h('div', { 'class': 'dhb-muted', text: s.date ? L.pickTime:L.pickDay }));
}
var go=$('[data-dhb-go]', this.el);
if(go) go.disabled = !t;
};
Shared.prototype.guestsText=function (n, k){
var ar=this.c.lang==='ar';
if(k==='a') return ar ? (n===1 ? 'بالغ واحد':n===2 ? 'بالغان':n <=10 ? n + ' بالغين':n + ' بالغًا'):(n===1 ? '1 adult':n + ' adults');
if(k==='i') return ar ? (n===1 ? 'رضيع واحد':n===2 ? 'رضيعان':n <=10 ? n + ' رضّع':n + ' رضيعًا'):(n===1 ? '1 infant':n + ' infants');
return ar ? (n===1 ? 'طفل واحد':n===2 ? 'طفلان':n <=10 ? n + ' أطفال':n + ' طفلًا'):(n===1 ? '1 child':n + ' children');
};
Shared.prototype.book=function (){
var t=this.cur(), s=this.s;
if(!t){ this.error(s.date ? this.L.pickTime:this.L.pickDay); return; }
this.hold({ o: s.opt.id, dep: t.dep, adults: s.adults, children: s.children, infants: s.infants, x: s.x });
};
Shared.prototype.afterError=function (){ if(this.s.date) this.pickDay(this.s.date); };
function Charter(el, c){
Box.call(this, el, c);
var w=this.want, opt=null;
c.opts.forEach(function (o){ if(String(o.id)===w.o) opt=o; });
this.s={ opt: opt||c.opts[0], extra: 0, month: null, days: {}, date: null, day: null, start: null, guests: Math.min(2, c.boat.guests), x: {}, singles: false };
if(opt&&w.x) this.s.extra=Math.max(0, Math.min(opt.maxExtra, +w.x||0));
if(opt&&w.a) this.s.guests=Math.max(1, Math.min(this.maxGuests(), +w.a||1));
if(!opt) this.want={};
this.wire();
this.drawLens();
this.loadMonth(monthOf(this.want.date)||monthOf(c.today), true);
}
Charter.prototype=Object.create(Box.prototype);
Charter.prototype.maxGuests=function (){ return Math.max(1, Math.min(this.s.opt.max||this.c.boat.guests, this.c.boat.guests)); };
Charter.prototype.drawLens=function (){
var self=this, s=this.s, L=this.L, box=clear($('[data-dhb-lens]', this.el));
this.c.opts.forEach(function (o){
var on=o.id===s.opt.id;
box.appendChild(h('button', { type: 'button', role: 'radio', 'aria-checked': on ? 'true':'false', 'class': 'dhb-len' + (on ? ' is-on':''),
onclick: function (){ if(on) return; self.used(); s.opt=o; s.extra=Math.min(s.extra, o.maxExtra); s.guests=Math.min(s.guests, self.maxGuests()); self.drawLens(); self.loadMonth(s.month, true); }},
[h('span', { 'class': 'dhb-len-l' }, [h('b', { text: o.name }), h('span', { 'class': 'dhb-small', text: o.note||o.dur })]), h('b', { text: self.money(self.offerPrice(o.price)) })]));
});
var xh=$('[data-dhb-xh]', this.el);
clear(xh);
xh.hidden = !(s.opt.extraPrice > 0&&s.opt.maxExtra > 0);
if(!xh.hidden){
xh.appendChild(this.stepper(L.extraHours, fmt(L.perExtraHour, this.money(s.opt.extraPrice)), s.extra, 0, s.opt.maxExtra, function (n){ s.extra=n; self.drawLens(); self.loadMonth(s.month, false); }, L.extraHours));
var b=$$('.dhb-pm', xh); if(b[0]) b[0].setAttribute('aria-label', L.hourLess); if(b[1]) b[1].setAttribute('aria-label', L.hourMore);
}};
Charter.prototype.loadMonth=function (month, seek, tries){
var self=this, c=this.c, s=this.s, n=++this.seq;
if(month < monthOf(c.today)) month=monthOf(c.today);
s.month=month;
this.api('charter', { o: s.opt.id, month: month, extra: s.extra }).then(function (j){
if(n!==self.seq) return;
if(!j||!j.ok){ self.error((j&&j.error)||self.L.error); return; }
var days={}, any=false;
(j.days||[]).forEach(function (d){ days[d.date]=d.state; if(d.state==='free'||d.state==='part') any=true; });
s.days=days;
if(seek&&!any&&month < monthOf(c.last)&&(tries||0) < 4){ self.loadMonth(addMonth(month, 1), true, (tries||0) + 1); return; }
var ok=function (k){ return days[k]==='free'||days[k]==='part'; };
var date=s.date&&ok(s.date) ? s.date:null;
if(!date&&self.want.date&&ok(self.want.date)) date=self.want.date;
if(!date&&seek) Object.keys(days).sort().some(function (k){ if(ok(k)){ date=k; return true; } return false; });
self.drawDays();
if(date) self.pickDay(date); else if(s.date&&s.date.slice(0, 7)===month) self.pickDay(s.date); else self.drawRest();
});
};
Charter.prototype.drawDays=function (){
var self=this, s=this.s, L=this.L, cells={};
Object.keys(s.days).forEach(function (k){
var st=s.days[k];
cells[k]=st==='booked' ? { off: true, cls: 'is-full', sub: L.bookedDay, aria: L.bookedLegend }
: st==='off' ? { off: true }
: { on: k===s.date, sub: st==='part' ? '●':'', aria: st==='part' ? L.partLegend:'', cls: st==='part' ? 'is-few':'' };});
this.drawCal(s.month, cells, function (date){ self.pickDay(date); });
};
Charter.prototype.pickDay=function (date){
var self=this, s=this.s, n=++this.seq;
s.date=date; this.drawDays(); this.error('');
this.api('charter', { o: s.opt.id, date: date, extra: s.extra }).then(function (j){
if(n!==self.seq) return;
s.day=j&&j.ok ? j:{ starts: [] };
var want=self.want.start, keep=null, first=null;
(s.day.starts||[]).forEach(function (x){ if(!x.ok) return; if(!first) first=x.time; if(x.time===s.start||x.time===want) keep=keep||x.time; });
if(want){ (s.day.starts||[]).forEach(function (x){ if(x.ok&&x.time===want) keep=want; });self.want.start=null; }
s.start=keep||first;
self.drawRest();
});
};
function s2e(s){ return s.start ? mins(s.start) + Math.round((s.opt.hours + s.extra) * 60):null; }
Charter.prototype.plan=function (){
var s=this.s, L=this.L, d=s.day||{}, st=mins(s.start), en=s2e(s), sun=d.sunset ? mins(d.sunset):null, out=[], hasSun=false;
if(sun!==null&&sun < st - 360) sun +=1440;
(d.steps||[]).forEach(function (x, i){
var t=(x.anchor==='end' ? en:st) + x.offset;
if(x.kind==='sunset'){ hasSun=true; if(sun===null||sun < st||sun > en) return; t=sun; }
out.push({ t: t, i: i, x: x });
});
var inTrip=sun!==null&&sun > st + 30&&sun < en - 10;
if(!hasSun&&inTrip) out.push({ t: sun, i: 999, x: { kind: 'sunset', title: L.sunsetTitle, note: L.sunsetStep }});
if(inTrip) out.forEach(function (o){ if(o.x.kind==='return'&&o.x.anchor==='end'&&o.x.offset < 0&&o.t <=sun) o.t=Math.min(en - 10, sun + 10); });
out.sort(function (a, b){ return a.t - b.t||a.i - b.i; });
return out;
};
Charter.prototype.drawRest=function (){
var self=this, s=this.s, L=this.L, c=this.c, d=s.day||{ starts: [] };
var win=$('[data-dhb-window]', this.el); if(win) win.textContent=fmt(L.between, this.time(s.opt.from), this.time(s.opt.to));
var grey=$('[data-dhb-greyed]', this.el); if(grey) grey.textContent=fmt(L.greyed, this.time(c.boat.latest));
var box=clear($('[data-dhb-starts]', this.el)), reasons={ 'too soon': L.rTooSoon, 'back too late': L.rTooLate, 'boat busy': L.rBusy };
(d.starts||[]).forEach(function (x){
var on=x.ok&&x.time===s.start;
box.appendChild(h('button', { type: 'button', 'class': 'dhb-start' + (on ? ' is-on':'') + (x.ok ? '':' is-off'), disabled: !x.ok, 'aria-pressed': on ? 'true':'false', 'data-time': x.time,
title: x.ok ? fmt(L.backAbout, self.time(x.end)):(reasons[x.reason]||''),
'aria-label': self.time(x.time) + ', ' + (x.ok ? fmt(L.backAbout, self.time(x.end)):fmt(L.notPossible, reasons[x.reason]||'')),
onclick: function (){ if(!x.ok) return; self.used(); s.start=x.time; self.drawRest(); }}, [self.time(x.time)]));
});
if(!s.date) box.appendChild(h('span', { 'class': 'dhb-muted dhb-small', text: L.pickDay }));
var planEl=clear($('[data-dhb-plan]', this.el));
if(s.start){
var st=mins(s.start), en=s2e(s);
var ol=h('ol', { 'class': 'dhb-plan' });
this.plan().forEach(function (p){
var x=p.x, sub=[x.place&&x.title.indexOf(x.place) < 0 ? x.place:'', x.note].filter(Boolean).join(' · ');
if(x.kind==='return'&&x.anchor==='end'&&x.offset===0&&s.extra) sub=[sub, fmt(L.withExtra, s.extra)].filter(Boolean).join(' · ');
ol.appendChild(h('li', {}, [h('span', { 'class': 'dhb-plan-t', text: self.time(hm(p.t)) }),
h('span', {}, [x.title, sub ? h('span', { 'class': 'dhb-plan-sub', text: sub }):null])]));
});
planEl.appendChild(h('div', { 'class': 'dhb-dayplan' }, [
h('div', { 'class': 'dhb-row dhb-row-wrap' }, [h('b', { text: L.yourDay }), h('b', { 'class': 'dhb-small', text: this.time(hm(st)) + ' – ' + this.time(hm(en)) })]),
ol, h('span', { 'class': 'dhb-tiny dhb-muted', text: L.dayNote })]));
}else if(s.date){
var why={}; (d.starts||[]).forEach(function (x){ if(!x.ok) why[x.reason]=(why[x.reason]||0) + 1; });
var txt=why['boat busy'] ? L.busy:why['back too late']&&!why['too soon'] ? fmt(L.tooLate, s.opt.hours + s.extra, this.time(c.boat.latest)):why['too soon'] ? L.tooSoon:L.pickStart;
planEl.appendChild(h('div', { 'class': 'dhb-warn', text: txt }));
}
var gEl=clear($('[data-dhb-guests]', this.el)), maxG=this.maxGuests();
if(s.guests > maxG) s.guests=maxG;
gEl.appendChild(this.stepper('4. ' + L.guests, fmt(L.guestsBoat, maxG), s.guests, 1, maxG, function (n){ s.guests=n; self.drawRest(); }, L.guests, 'is-big'));
this.drawExtras();
var sum=clear($('[data-dhb-sum]', this.el)), lines=[], total=0, kind=c.boat.kind==='yacht' ? L.yacht:L.boat;
var when=s.date ? this.day(s.date) + ' · ' + (s.start ? this.time(s.start) + ' – ' + this.time(hm(s2e(s))):L.chooseStartFirst):L.pickDay;
sum.appendChild(h('div', { 'class': 'dhb-sum-when', text: when + ' · ' + this.count('guests', s.guests) }));
lines.push([s.opt.name + (s.start ? ' · ' + this.time(s.start) + '–' + this.time(hm(s2e(s))):'') + ' · ' + fmt(L.wholeBoat, kind), this.offerPrice(s.opt.price)]);
if(s.extra) lines.push([fmt(L.extraLine, s.extra, this.money(s.opt.extraPrice)), s.extra * s.opt.extraPrice]);
c.extras.forEach(function (x){
var q=s.x[x.id]||0;
if(!q) return;
var amt=x.kind==='per_person' ? x.price * q:(x.basis==='person' ? x.price * s.guests:x.price);
lines.push([(q > 1||x.kind==='per_person' ? q + ' × ':'') + x.name, amt]);
});
lines.forEach(function (l){ total +=l[1]; sum.appendChild(h('div', { 'class': 'dhb-line' }, [h('span', { text: l[0] }), h('span', { text: self.money(l[1]) })])); });
sum.appendChild(h('div', { 'class': 'dhb-total' }, [h('b', { text: L.total }), h('span', { text: this.money(total) })]));
this.bar(this.money(total), [s.opt.name + (s.extra ? ' + ' + s.extra:''), s.date ? this.day(s.date, true):'', s.start ? this.time(s.start) + '–' + this.time(hm(s2e(s))):''].filter(Boolean).join(' · '));
var go=$('[data-dhb-go]', this.el); if(go) go.disabled = !s.start;
};
Charter.prototype.drawExtras=function (){
var self=this, s=this.s, L=this.L, c=this.c, ex=clear($('[data-dhb-extras]', this.el)), sec=$('[data-dhb-extsec]', this.el);
sec.hidden = !c.extras.length;
var startTs=s.start ? this.ts(s.date, s.start):0;
var role=function (r){ return c.extras.filter(function (x){ return x.kind==='per_person'&&x.role===r; });};
var q=function (x){ return s.x[x.id]||0; };
var sumOf=function (list){ return list.reduce(function (a, x){ return a + q(x); }, 0); };
var maxOf=function (list){ return list.reduce(function (a, x){ return Math.max(a, q(x)); }, 0); };
var divers=role('divers'), sets=role('gear_set'), items=role('gear_item'), tries=role('try');
var clamp=function (){
var g=s.guests;
divers.forEach(function (x){ s.x[x.id]=Math.min(q(x), g); });
var dv=sumOf(divers);
tries.forEach(function (x){ s.x[x.id]=Math.min(q(x), Math.max(0, g - dv)); });
sets.forEach(function (x){ s.x[x.id]=Math.min(q(x), dv); });
var st=sumOf(sets);
items.forEach(function (x){ s.x[x.id]=Math.min(q(x), Math.max(0, dv - st)); });
c.extras.forEach(function (x){ if(x.kind==='per_person'&&['divers', 'gear_set', 'gear_item', 'try'].indexOf(x.role) < 0) s.x[x.id]=Math.min(q(x), Math.min(g, x.max||g)); });
};
clamp();
var priceSub=function (x){ return [x.desc, self.money(x.price)].filter(Boolean).join(' · '); };
var row=function (x, max, cls){
var nt=self.notice(x, startTs), late = !nt[1];
if(late) s.x[x.id]=0;
var r=self.stepper(x.name, priceSub(x), q(x), 0, late ? 0:Math.max(0, max), function (n){ s.x[x.id]=n; self.drawRest(); }, x.name, cls);
return nt[0] ? h('div', {}, [r, h('div', { 'class': 'dhb-notice ' + (late ? 'is-late':'is-ok'), text: nt[0] })]):r;
};
if(divers.length||tries.length){
var dv=sumOf(divers), grp=h('div', { 'class': 'dhb-group' }, [h('b', { 'class': 'dhb-group-h', text: L.diving })]);
divers.forEach(function (x){ grp.appendChild(row(x, s.guests - sumOf(tries) - (dv - q(x)))); });
if(dv > 0&&(sets.length||items.length)){
var st=sumOf(sets), mi=maxOf(items);
var gear=h('div', { 'class': 'dhb-gear' }, [h('div', { 'class': 'dhb-row' }, [h('b', { 'class': 'dhb-small', text: fmt(L.gearFor, dv) }), h('span', { 'class': 'dhb-tiny dhb-muted', text: L.ownGear })])]);
sets.forEach(function (x){ gear.appendChild(row(x, dv - mi - (st - q(x)), 'is-small')); });
if(items.length){
gear.appendChild(h('button', { type: 'button', 'class': 'dhb-link', 'aria-expanded': s.singles ? 'true':'false', text: s.singles ? L.singlesHide:L.singles,
onclick: function (){ s.singles = !s.singles; if(!s.singles) items.forEach(function (x){ s.x[x.id]=0; });self.drawRest(); }}));
if(s.singles) items.forEach(function (x){ gear.appendChild(row(x, dv - st, 'is-small')); });
}
gear.appendChild(h('span', { 'class': 'dhb-tiny dhb-muted', text: L.sizes }));
grp.appendChild(gear);
}
if(tries.length){
var tw=h('div', { 'class': 'dhb-try' });
tries.forEach(function (x){ tw.appendChild(row(x, s.guests - dv - (sumOf(tries) - q(x)))); });
if(sumOf(tries) > 0) tw.appendChild(h('div', { 'class': 'dhb-trynote', text: fmt(L.tryNote, sumOf(tries)) }));
grp.appendChild(tw);
}
ex.appendChild(grp);
}
c.extras.forEach(function (x){
if(x.kind==='per_person'&&['divers', 'gear_set', 'gear_item', 'try'].indexOf(x.role) >=0) return;
if(x.kind==='per_person'){ ex.appendChild(row(x, Math.min(s.guests, x.max||s.guests))); return; }
var nt=self.notice(x, startTs), late = !nt[1];
if(late) delete s.x[x.id];
var info=[x.includes&&x.includes.length ? x.includes.join(self.comma()):x.desc, self.money(x.price) + (x.basis==='person' ? ' · ' + L.perPersonShort:'')].filter(Boolean).join(' · ');
ex.appendChild(h('label', { 'class': 'dhb-tick' + (late ? ' is-late':'') }, [
h('input', { type: 'checkbox', checked: !!s.x[x.id], disabled: late, onchange: function (ev){ self.used(); if(ev.target.checked) s.x[x.id]=1; else delete s.x[x.id]; self.drawRest(); }}),
h('span', {}, [h('span', { text: x.name }), h('span', { 'class': 'dhb-muted dhb-small', text: ' · ' + info }), nt[0] ? h('span', { 'class': 'dhb-notice ' + (late ? 'is-late':'is-ok'), text: nt[0] }):null])]));
});
};
Charter.prototype.book=function (){
var s=this.s;
if(!s.date){ this.error(this.L.pickDay); return; }
if(!s.start){ this.error(this.L.pickStart); return; }
this.hold({ o: s.opt.id, date: s.date, start: s.start, extra: s.extra, adults: s.guests, children: 0, x: s.x });
};
Charter.prototype.afterError=function (){ if(this.s.date) this.pickDay(this.s.date); };
function init(scope){
$$('[data-dh-box]', scope||document).forEach(function (el){
if(el.dhb||el.getAttribute('data-dh-box')==='enquiry') return;
var raw=$('script[data-dhb-conf]', el), c=null;
try { c=JSON.parse(raw ? raw.textContent:'null'); } catch (e){ c=null; }
if(!c||!window.fetch||!window.URLSearchParams) return;
el.classList.add('is-ready');
try { el.dhb=el.getAttribute('data-dh-box')==='charter' ? new Charter(el, c):new Shared(el, c); } catch (e){ if(window.console) console.error(e); }});
}
DH.initBoxes=init;
document.addEventListener('dh:mounted', function (ev){ init(ev.target&&ev.target.querySelectorAll ? ev.target:document); });
if(document.readyState==='loading') document.addEventListener('DOMContentLoaded', function (){ init(document); });else init(document);
})();