/** * WPBC calendar loader bootstrap. * ============================================================================================== * - Finds every .calendar_loader_frame[data-wpbc-rid] on the page (now or later). * - For each loader element, waits a "grace" period (data-wpbc-grace, default 8000 ms): * - If the real calendar appears: do nothing (loader naturally replaced). * - If not: show a helpful message (missing jQuery/_wpbc/datepick) or a duplicate notice. * - Works with multiple calendars and even duplicate RIDs on the same page. * - No inline JS needed in the shortcode/template output. * * File: ../includes/__js/client/cal/wpbc_cal_loader.js * * @since 10.14.5 * @modified 2025-09-07 12:21 * @version 1.0.0 * */ /** * WPBC calendar loader bootstrap. * - Auto-detects .calendar_loader_frame[data-wpbc-rid] blocks. * - Waits a "grace" period per element before showing a helpful message * if the real calendar hasn't replaced the loader. * - Multiple calendars and duplicate RIDs are handled. */ (function (w, d) { 'use strict'; /* --------------------------------------------------------------------------- * Small utilities (snake_case) * ------------------------------------------------------------------------ */ /** Track processed loader elements; fallback to data flag if WeakSet missing. */ var processed_set = typeof WeakSet === 'function' ? new WeakSet() : null; /** Return first match inside optional root. */ function query_one(selector, root) { return (root || d).querySelector( selector ); } /** Return NodeList of matches inside optional root. */ function query_all(selector, root) { return (root || d).querySelectorAll( selector ); } /** Run a callback when DOM is ready. */ function on_ready(fn) { if ( d.readyState === 'loading' ) { d.addEventListener( 'DOMContentLoaded', fn ); } else { fn(); } } /** Clear interval safely. */ function safe_clear(interval_id) { try { w.clearInterval( interval_id ); } catch ( e ) { } } /** Mark element processed (WeakSet or data attribute). */ function mark_processed(el) { if ( processed_set ) { processed_set.add( el ); } else { try { el.dataset.wpbcProcessed = '1'; } catch ( e ) { } } } /** Check if element was processed. */ function is_processed(el) { return processed_set ? processed_set.has( el ) : (el && el.dataset && el.dataset.wpbcProcessed === '1'); } /* --------------------------------------------------------------------------- * Messages * ------------------------------------------------------------------------ */ /** * Build visitor messages for a resource, using localized Form Messages when available. * @param {string|number} rid * @return {{duplicate:string,init_failed:string,support:string,lib_jq:string,lib_dp:string,lib_wpbc:string}} */ function get_messages(rid) { var rid_int = parseInt( rid, 10 ); var duplicate_message = 'More than one calendar or booking form for Booking Resource ID {resource_id} is present on this page. ' + 'A hidden copy still conflicts with the visible form and can prevent booking submission. ' + 'The site administrator must keep only one calendar or form for this Booking Resource. ' + 'After the page is corrected, reload it and try again.'; if ( w._wpbc && typeof w._wpbc.get_message === 'function' ) { duplicate_message = w._wpbc.get_message( 'message_duplicate_booking_resource_on_page' ) || duplicate_message; } duplicate_message = String( duplicate_message ).replace( /\{resource_id\}/g, String( rid_int ) ); return { duplicate : duplicate_message, init_failed: 'The calendar could not be initialized on this page.' + '\n' + 'Please check your browser console for JavaScript errors and conflicts with other scripts/plugins.', support : '', /* 'Contact support@wpbookingcalendar.com if you have any questions.', */ lib_jq : 'It appears that the "jQuery" library is not loading correctly.' + '\n' + 'For more information, please refer to this page: https://wpbookingcalendar.com/faq/', lib_dp : 'It appears that the "jQuery.datepick" library is not loading correctly.' + '\n' + 'For more information, please refer to this page: https://wpbookingcalendar.com/faq/', lib_wpbc : 'It appears that the "_wpbc" library is not loading correctly.' + '\n' + 'Please enable the loading of JS/CSS files for this page on the "WP Booking Calendar" - "Settings General" - "Advanced" page' + '\n' + 'For more information, please refer to this page: https://wpbookingcalendar.com/faq/' }; } /** * Escape a plain-text loader message before inserting its wrapper markup. * * @param {string} plain_text Visitor-facing plain text. * @return {string} HTML-safe text. */ function escape_html(plain_text) { return String( plain_text || '' ) .replace( /&/g, '&' ) .replace( //g, '>' ) .replace( /"/g, '"' ) .replace( /'/g, ''' ); } /** * Wrap plain text (with newlines) in a small HTML container. * @param {string} msg * @return {string} */ function wrap_html(msg) { return '