The mtolives-book-now widget is a lightweight, self-hosted Web Component (Custom Element + Shadow DOM) that renders a two-field date-range picker (Check-in / Check-out) and a BOOK NOW button. It navigates to the Cloudbeds booking engine with the selected dates passed as query parameters. It was built to closely match the visual and behavioral feel of the original Site Editor/Cloudbeds header widget, while removing platform lock-in so it can be hosted on your own cPanel or any standard web server.
<mtolives-book-now> with Shadow DOM isolation.rangePlugin (one popup controls both inputs).<body>) is consistently styled.{book-url}?checkin=YYYY-MM-DD&checkout=YYYY-MM-DD (local-time safe) and redirects.locale attribute loads Flatpickr locale; RTL flip for Arabic/Hebrew (sets dir="rtl" on host).book-url, show-months (1 or 2), popup position (above/below/auto), display-format, locale.rangePlugin.document.body.rangePlugin, optional locale packs (he, ar, tr, ru, ko).widgets/
└─ mtolives-book-now/
├─ mtolives-book-now.js
├─ vendor/
│ └─ flatpickr/
│ ├─ flatpickr.min.css
│ ├─ flatpickr.min.js
│ ├─ plugins/
│ │ └─ rangePlugin.js
│ └─ l10n/ (optional locales: he.js, ar.js, tr.js, ru.js, ko.js …)
├─ demo/
│ └─ index.html
├─ VERSION
├─ CHANGELOG.md
├─ LICENSE
└─ README.md
<script defer src="/widgets/mtolives-book-now/mtolives-book-now.js?v=1.0.0"></script>
<mtolives-book-now
book-url="https://www.mtoliveshotel.com/book-now"
show-months="2"
popup="above"
display-format="d M Y"
locale="en">
</mtolives-book-now>
book-url (string): Absolute or relative URL to booking engine entry page.show-months (1|2): Months shown in the popup (default 2).popup (above|below|auto|variants): Preferred popup position (default above).display-format (string): Visible date format (e.g., d M Y).locale (string): Flatpickr locale key (e.g., en, he, ar, tr, ru, ko).On BOOK NOW, the widget navigates to:
{book-url}?checkin=YYYY-MM-DD&checkout=YYYY-MM-DD
selectedDates in local time.CSS variables on :host allow easy theming:
--olive, --hover-blue, --teal — button/hover colors and inner field frame.--fieldW, --fieldH — field width/height.--radius — 0 for square; e.g., 6px for rounded.--gap — spacing between fields/button.All other styles are isolated in Shadow DOM. The only global CSS is a small calendar “polish” style injected to <head> to style the popup appended to <body>.
<label for="…">) and aria-labels present.locale="…" to load Flatpickr localization (local vendor path or CDN fallback).dir="rtl" on the host to flip layout direction.text/javascript).?v={VERSION} on deployments to bust caches.MAJOR.MINOR.PATCH).VERSION, CHANGELOG.md, and LICENSE in the folder.?v=1.0.0 when you deploy a new release. Optionally tag releases in Git (e.g., v1.0.0).<body>; needs global CSS injection (the widget does this automatically).body { display:flex; } can make missing CSS more obvious—ensure flatpickr.min.css loads (local or CDN)..js file doesn’t contain <script> tags and that the path isn’t 404’ing to an HTML error page.onDayCreate with month caching (requires server endpoint).await ensureFlatpickrLoaded(locale);
this.fpRange = flatpickr(checkin, {
locale,
dateFormat: displayFormat,
showMonths,
position,
plugins: [ new rangePlugin({ input: checkout }) ],
onChange: (dates) => {
const [ci, co] = dates;
checkin.value = ci ? flatpickr.formatDate(ci, displayFormat) : '';
checkout.value = co ? flatpickr.formatDate(co, displayFormat) : '';
},
});
// on click:
const url = new URL(bookUrl, location.origin);
url.searchParams.set('checkin', toYMD(checkIn));
url.searchParams.set('checkout', toYMD(checkOut));
location.href = url.toString();
LICENSE if you self-host vendor files).selectedDates.rangePlugin; correct in-calendar range highlighting.