{"id":11,"date":"2026-03-31T20:35:45","date_gmt":"2026-03-31T20:35:45","guid":{"rendered":"https:\/\/bpr.williehowe.com\/index.php\/facilities-calendar\/"},"modified":"2026-03-31T20:35:45","modified_gmt":"2026-03-31T20:35:45","slug":"facilities-calendar","status":"publish","type":"page","link":"https:\/\/bpr.williehowe.com\/index.php\/facilities-calendar\/","title":{"rendered":"Facilities Calendar"},"content":{"rendered":"<style>\n.bpr-cal-dialog:not([open]){display:none}\n.fc .bpr-calendar-entry{display:grid;gap:5px;padding:9px 10px;white-space:normal;overflow-wrap:anywhere;font:15px\/1.4 system-ui,sans-serif;color:inherit;text-align:left}.fc .bpr-calendar-entry__time{display:block;font-size:14px;font-weight:700}.fc .bpr-calendar-entry__title{display:block;font-size:16px;font-weight:700}.fc .bpr-calendar-entry__facility{display:block;font-size:15px;font-weight:500}.fc .fc-daygrid-block-event .fc-event-main{color:#fff}.fc .fc-daygrid-block-event .fc-event-main-frame{display:block}.fc .fc-popover{max-width:350px}.fc .fc-popover .bpr-calendar-entry{min-width:200px}\n.bpr-calendar-wrap .fc,.bpr-portal-card .fc,.bpr-admin-card .fc{--fc-button-bg-color:var(--bpr-primary,#2d6a4f);--fc-button-border-color:var(--bpr-primary,#2d6a4f);--fc-button-hover-bg-color:#1b4332;--fc-button-hover-border-color:#1b4332;--fc-button-active-bg-color:#1b4332;--fc-button-active-border-color:#1b4332}\n.fc .fc-event{cursor:pointer}.fc .fc-event:focus-visible{outline:3px solid #e67e22;outline-offset:2px}.fc .fc-daygrid-event{white-space:normal;align-items:flex-start}.fc .fc-event-time{white-space:normal}.fc .bpr-event-location{display:block;font-size:.88em;font-weight:400;overflow-wrap:anywhere}.bpr-calendar-help{color:#52616b;font-size:14px;margin:12px 0}.bpr-calendar-toolbar{display:flex;flex-wrap:wrap;align-items:end;justify-content:space-between;gap:12px;margin-bottom:16px}\n.bpr-cal-tooltip{position:fixed;z-index:100010;width:min(320px,calc(100vw - 24px));padding:14px 16px;background:#fff;color:#173e2c;border:1px solid #cbded5;border-left:4px solid #2d6a4f;border-radius:10px;box-shadow:0 8px 28px #10271933;pointer-events:none;font:14px\/1.5 system-ui,sans-serif;overflow-wrap:anywhere}.bpr-cal-tooltip strong{display:block;margin-bottom:4px}.bpr-cal-tooltip div+div{margin-top:4px}\n.bpr-cal-dialog{box-sizing:border-box;width:min(540px,calc(100vw - 32px));max-height:calc(100dvh - 32px);margin:auto;padding:0;border:0;border-radius:16px;background:#fff;color:#173e2c;box-shadow:0 20px 70px #12271c44;font:16px\/1.5 system-ui,sans-serif;overflow:auto}.bpr-cal-dialog::backdrop{background:#10271c99}.bpr-cal-dialog[open]{display:block}.bpr-cal-dialog__header{display:flex;justify-content:space-between;gap:16px;align-items:start;background:#f1f7f4;padding:22px 24px;border-bottom:1px solid #dce8e2}.bpr-cal-dialog h2{font:700 23px\/1.3 system-ui,sans-serif;margin:6px 0 0;color:#173e2c;overflow-wrap:anywhere}.bpr-cal-dialog__type{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.06em}.bpr-cal-dialog__close{flex-shrink:0;min-width:44px;min-height:44px;border:1px solid #cbded5;border-radius:50%;background:#fff;color:#173e2c;cursor:pointer;font-size:24px}.bpr-cal-dialog__body{padding:22px 24px}.bpr-cal-dialog dl{margin:0}.bpr-cal-dialog dt{font-size:13px;font-weight:700;color:#52616b;margin-top:16px}.bpr-cal-dialog dt:first-child{margin-top:0}.bpr-cal-dialog dd{margin:4px 0 0;overflow-wrap:anywhere}.bpr-cal-dialog__zone{font-size:13px;color:#52616b;margin:16px 0 0}.bpr-cal-dialog__actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:22px}.bpr-cal-dialog__actions a,.bpr-cal-dialog__actions button{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:10px 18px;border:1px solid #2d6a4f;border-radius:8px;background:#2d6a4f;color:#fff;font:600 14px\/1.5 system-ui,sans-serif;text-decoration:none;cursor:pointer}.bpr-cal-dialog__actions button{background:#fff;color:#2d6a4f}.bpr-cal-dialog__fallback[open]{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;z-index:100011;box-shadow:0 0 0 100vmax #10271c99}\n@media(max-width:640px){.fc .fc-header-toolbar{flex-direction:column;align-items:stretch;gap:12px}.fc .fc-toolbar-chunk{text-align:center}.fc .fc-toolbar-title{font-size:1.3em}.fc .fc-button{padding:.5em .65em;font-size:.88em;min-height:40px}.fc .fc-daygrid-event{font-size:11px}.fc .fc-daygrid-dot-event{display:block}.fc .fc-daygrid-event-dot{display:none}.fc .fc-col-header-cell-cushion{padding:6px 2px;font-size:12px}.bpr-cal-dialog__header,.bpr-cal-dialog__body{padding:18px}.bpr-cal-dialog__actions>*{width:100%}.bpr-cal-dialog h2{font-size:21px}}\n<\/style>\n<script>\n(function () {\n    'use strict';\n    if (window.bprCalendarUI) return;\n    var tooltip, dialog, returnFocus;\n    function node(tag, text, className) {\n        var el = document.createElement(tag);\n        if (text !== undefined) el.textContent = text;\n        if (className) el.className = className;\n        return el;\n    }\n    function hideTooltip() { if (tooltip) { tooltip.remove(); tooltip = null; } }\n    function closeDialog() {\n        if (!dialog) return;\n        if (typeof dialog.close === 'function') dialog.close();\n        else { dialog.removeAttribute('open'); if (returnFocus && returnFocus.isConnected) returnFocus.focus(); }\n    }\n    function showDetails(event, config, trigger) {\n        hideTooltip();\n        var p = event.extendedProps || {};\n        if (!dialog) {\n            dialog = node('dialog', undefined, 'bpr-cal-dialog');\n            dialog.setAttribute('aria-labelledby', 'bpr-cal-detail-title');\n            dialog.addEventListener('click', function (e) { if (e.target === dialog) closeDialog(); });\n            dialog.addEventListener('close', function () { if (returnFocus && returnFocus.isConnected) returnFocus.focus(); });\n            dialog.addEventListener('keydown', function (e) {\n                if (e.key === 'Escape') { e.preventDefault(); closeDialog(); }\n                if (e.key === 'Tab') {\n                    var targets = dialog.querySelectorAll('button,a[href]');\n                    var first = targets[0], last = targets[targets.length - 1];\n                    if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }\n                    else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }\n                }\n            });\n            document.body.appendChild(dialog);\n        }\n        dialog.replaceChildren();\n        returnFocus = trigger || document.activeElement;\n        var header = node('div', undefined, 'bpr-cal-dialog__header');\n        var heading = node('div');\n        heading.appendChild(node('span', p.event_type || 'Calendar entry', 'bpr-cal-dialog__type'));\n        var title = node('h2', event.title); title.id = 'bpr-cal-detail-title'; heading.appendChild(title);\n        header.appendChild(heading);\n        var close = node('button', '\u00d7', 'bpr-cal-dialog__close'); close.type = 'button';\n        close.setAttribute('aria-label', 'Close calendar details'); close.addEventListener('click', closeDialog); header.appendChild(close);\n        dialog.appendChild(header);\n        var body = node('div', undefined, 'bpr-cal-dialog__body'), dl = node('dl');\n        function row(label, value) { if (value) { dl.appendChild(node('dt', label)); dl.appendChild(node('dd', value)); } }\n        row('Facility \/ Location', p.facility || 'Location not provided');\n        row(event.allDay ? 'Date' : 'Starts', p.start_label);\n        if (!event.allDay) row('Ends', p.end_label || 'End time not provided');\n        row('Reservation number', p.reservation_num);\n        row('Status', p.status ? String(p.status).replace(\/_\/g, ' ') : '');\n        body.appendChild(dl);\n        if (p.timezone) body.appendChild(node('p', 'Times shown in ' + p.timezone + '.', 'bpr-cal-dialog__zone'));\n        var actions = node('div', undefined, 'bpr-cal-dialog__actions');\n        var url = event.url, label = 'View Event';\n        if (\/^res-\\d+$\/.test(event.id) && config.reservationUrl) {\n            url = config.reservationUrl + event.id.substring(4); label = 'Open Reservation';\n        }\n        if (url && \/^(https?:\\\/\\\/|\\\/)\/i.test(url)) {\n            var link = node('a', label); link.href = url; actions.appendChild(link);\n        }\n        var done = node('button', 'Close'); done.type = 'button'; done.addEventListener('click', closeDialog);\n        actions.appendChild(done); body.appendChild(actions); dialog.appendChild(body);\n        if (typeof dialog.showModal === 'function') { if (!dialog.open) dialog.showModal(); }\n        else { dialog.classList.add('bpr-cal-dialog__fallback'); dialog.setAttribute('role', 'dialog'); dialog.setAttribute('aria-modal', 'true'); dialog.setAttribute('open', ''); }\n        close.focus();\n    }\n    function showTooltip(info) {\n        hideTooltip();\n        var p = info.event.extendedProps || {};\n        tooltip = node('div', undefined, 'bpr-cal-tooltip'); tooltip.setAttribute('role', 'tooltip');\n        tooltip.appendChild(node('strong', info.event.title));\n        tooltip.appendChild(node('div', p.facility || 'Location not provided'));\n        tooltip.appendChild(node('div', p.range_label || p.start_label || ''));\n        document.body.appendChild(tooltip);\n        var rect = info.el.getBoundingClientRect(), box = tooltip.getBoundingClientRect();\n        tooltip.style.left = Math.max(12, Math.min(rect.left, window.innerWidth - box.width - 12)) + 'px';\n        tooltip.style.top = Math.max(12, rect.bottom + box.height + 8 <= window.innerHeight ? rect.bottom + 8 : rect.top - box.height - 8) + 'px';\n    }\n    function options(config) {\n        config = config || {};\n        return {\n            initialView:'dayGridMonth', height:'auto', firstDay:config.firstDay || 0,\n            headerToolbar:{left:'prev,next today', center:'title', right:'dayGridMonth,timeGridWeek,timeGridDay,listWeek'},\n            buttonText:{month:'Month', week:'Week', day:'Day', list:'List'},\n            displayEventEnd:true,\n            \/\/ Event UI colors are built from the root options in FullCalendar 6.\n            \/\/ A view-only display setting leaves single-day bookings as links.\n            eventDisplay:'block',\n            views:{dayGridMonth:{dayMaxEvents:4,eventContent:function(info){\n                var p=info.event.extendedProps || {}, card=node('div',undefined,'bpr-calendar-entry');\n                card.appendChild(node('span',p.time_label || info.timeText || (info.event.allDay ? 'All day' : ''),'bpr-calendar-entry__time'));\n                card.appendChild(node('strong',info.event.title,'bpr-calendar-entry__title'));\n                if(p.facility)card.appendChild(node('span',p.facility,'bpr-calendar-entry__facility'));\n                return {domNodes:[card]};\n            }}},\n            eventTimeFormat:{hour:'numeric', minute:'2-digit', meridiem:'short', hour12:true},\n            eventDidMount:function (info) {\n                var p = info.event.extendedProps || {};\n                info.el.setAttribute('tabindex', '0'); info.el.setAttribute('role', 'button');\n                info.el.setAttribute('aria-label', [info.event.title, p.facility, p.range_label, 'Open details'].filter(Boolean).join('. '));\n                var titleEl = info.el.querySelector('.fc-event-title') || info.el.querySelector('.fc-list-event-title');\n                if (titleEl && p.facility) titleEl.appendChild(node('span', p.facility, 'bpr-event-location'));\n                info.el.addEventListener('keydown', function (e) {\n                    if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); showDetails(info.event, config, info.el); }\n                });\n                info.el.addEventListener('focus', function () { showTooltip(info); });\n                info.el.addEventListener('blur', hideTooltip);\n            },\n            eventMouseEnter:showTooltip, eventMouseLeave:hideTooltip,\n            eventClick:function (info) { info.jsEvent.preventDefault(); showDetails(info.event, config, info.el); },\n            datesSet:hideTooltip\n        };\n    }\n    function printUrl(cal, base, facility) {\n        var url = new URL(base, window.location.href);\n        var views = {dayGridMonth:'month',timeGridWeek:'week',timeGridDay:'day',listWeek:'list'};\n        var date = cal.getDate();\n        var value = date.getFullYear() + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0');\n        url.searchParams.set('view', views[cal.view.type] || 'month');\n        url.searchParams.set('date', value);\n        url.searchParams.set('facility_id', facility ? facility.value : '0');\n        return url.href;\n    }\n    function bindPrint(cal, button, facility, base) {\n        if (!button) return;\n        function update() { button.href = printUrl(cal, base, facility); }\n        button.addEventListener('click', update);\n        cal.on('datesSet', update);\n        if (facility) facility.addEventListener('change', update);\n        update();\n    }\n    window.addEventListener('scroll', hideTooltip, true);\n    window.addEventListener('resize', hideTooltip);\n    function bindImport(cal, facility) {\n        document.addEventListener('bpr:calendar-imported', function (event) {\n            if (!event.detail || !event.detail.imported) return;\n            if (facility) facility.value = '0';\n            if (event.detail.firstDate) cal.gotoDate(event.detail.firstDate);\n            cal.refetchEvents();\n            if (facility) facility.dispatchEvent(new Event('change'));\n        });\n    }\n    window.bprCalendarUI = {options:options, bindPrint:bindPrint, printUrl:printUrl, bindImport:bindImport};\n})();\n<\/script>\n        <div class=\"bpr-calendar-wrap\">\n    <div class=\"bpr-calendar-toolbar\">\n            <div class=\"bpr-cal-filter\">\n        <label for=\"bpr-cal-facility\">Filter by Facility:<\/label>\n        <select id=\"bpr-cal-facility\">\n            <option value=\"0\">All Facilities<\/option>\n                            <option value=\"1\">Alpha Park Clubhouse<\/option>\n                            <option value=\"2\">Alpha Park - Blanquart Pavilion<\/option>\n                            <option value=\"3\">Alpha Park - Lions Club Pavilion<\/option>\n                            <option value=\"4\">Lauterbach Pavilion<\/option>\n                            <option value=\"5\">Zeller Pavilion<\/option>\n                            <option value=\"6\">Ball Diamond 1<\/option>\n                            <option value=\"7\">Ball Diamond 2<\/option>\n                            <option value=\"8\">Ball Diamond 3<\/option>\n                            <option value=\"9\">Ball Diamond 4<\/option>\n                            <option value=\"10\">Ball Diamond 5<\/option>\n                            <option value=\"11\">Cross Country Trail<\/option>\n                            <option value=\"12\">Disc Golf Course<\/option>\n                    <\/select>\n    <\/div>\n        <a id=\"bpr-public-print-calendar\" href=\"https:\/\/bpr.williehowe.com\/?bpr_print_calendar=1&#038;scope=public\" target=\"_blank\" rel=\"noopener\" class=\"bpr-btn bpr-btn-outline\">Print Calendar<\/a>\n    <\/div>\n    <div class=\"bpr-legend\">\n        <span class=\"bpr-legend-item bpr-legend--reserved\">Reserved<\/span>\n        <span class=\"bpr-legend-item bpr-legend--event\">Park Event<\/span>\n        <span class=\"bpr-legend-item bpr-legend--blocked\">Unavailable<\/span>\n    <\/div>\n    <p class=\"bpr-calendar-help\">Click or tap an entry for the facility and full start\/end times. Hover for a quick preview.<\/p>\n    <p class=\"bpr-calendar-scroll-help\">On smaller screens, swipe across the month calendar or choose List for a larger, stacked view.<\/p>\n        <div id=\"bpr-public-calendar-status\" class=\"bpr-form-message\" role=\"status\" hidden><\/div>\n    <div id=\"bpr-frontend-calendar\" data-first-day=\"1\" data-view=\"dayGridMonth\"><\/div>\n    <p class=\"bpr-cal-cta\"><a href=\"https:\/\/bpr.williehowe.com\/index.php\/make-a-reservation\/\" class=\"bpr-btn bpr-btn-primary\">Make a Reservation<\/a><\/p>\n<\/div>\n\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-11","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/bpr.williehowe.com\/index.php\/wp-json\/wp\/v2\/pages\/11","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bpr.williehowe.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bpr.williehowe.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bpr.williehowe.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bpr.williehowe.com\/index.php\/wp-json\/wp\/v2\/comments?post=11"}],"version-history":[{"count":0,"href":"https:\/\/bpr.williehowe.com\/index.php\/wp-json\/wp\/v2\/pages\/11\/revisions"}],"wp:attachment":[{"href":"https:\/\/bpr.williehowe.com\/index.php\/wp-json\/wp\/v2\/media?parent=11"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}