1/** 2 * Hydrogen Calendar Embeds - Tooltip Renderer 3 * 4 * Renders event tooltips using Tippy.js. Handles event details display 5 * including time, location, description, and action buttons. 6 * 7 * @package hydrogen-calendar-embeds 8 * @since 1.0.0 9 */ 10 11function hycal_tippyRender(info, currCal, hycalSettings) { 12 // console.log(info.event); // DEBUG 13 // console.table(info.event.extendedProps); // DEBUG 14 // console.log(info.el.classList); // DEBUG 15 16 // Extract calendar index from event element for styling 17 let popupClass = ""; 18 for (let className of info.el.classList) { 19 if (className.startsWith("hycal-event-")) { 20 const calendarIndex = className.replace("hycal-event-", ""); 21 popupClass = `hycal-calendar-${calendarIndex}-popup`; 22 break; 23 } 24 } 25 26 const startTime = info.event.allDay 27 ? "All Day" 28 : new Date(info.event.startStr).toLocaleTimeString([], { 29 hour: "numeric", 30 minute: "2-digit", 31 }); 32 33 // Check if displayEventEnd is disabled via fc_args 34 let displayEventEnd = true; 35 if (hycalSettings && hycalSettings["fc_args"]) { 36 try { 37 const fcArgs = JSON.parse(hycalSettings["fc_args"]); 38 if (fcArgs.hasOwnProperty("displayEventEnd")) { 39 displayEventEnd = fcArgs.displayEventEnd; 40 } 41 } catch (e) { 42 // Invalid JSON, use default 43 } 44 } 45 46 const endTime = 47 !displayEventEnd || info.event.allDay 48 ? "" 49 : " - " + 50 new Date(info.event.endStr).toLocaleTimeString([], { 51 hour: "numeric", 52 minute: "2-digit", 53 }); 54 55 const location = info.event.extendedProps.location || ""; 56 57 const locString = location 58 ? `<p class="hycal-event-location"><a href="https://www.google.com/maps/search/?api=1&query=${encodeURIComponent( 59 location 60 )}" target="_blank" rel="noopener noreferrer" class="hycal-event-location-link"><svg class="hycal-location-icon" viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M12 2C7.58 2 4 5.58 4 10c0 5.25 8 13 8 13s8-7.75 8-13c0-4.42-3.58-8-8-8zm0 11c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z"/></svg><span>${location}</span></a></p>` 61 : ""; 62 63 // Handle free/busy calendars with undefined titles 64 // Google Calendar API returns the string "undefined" for free/busy events 65 const eventTitle = 66 !info.event.title || info.event.title === "undefined" 67 ? wp.i18n.__("Busy", "hydrogen-calendar-embeds") 68 : info.event.title; 69 70 /** 71 * Filter: hycal.tooltipHeader 72 * 73 * Filter the tooltip header HTML (close button, title, time, location). 74 * 75 * @since 1.0.0 76 * 77 * @param {string} headerHtml The header HTML. 78 * @param {object} info FullCalendar event info object. 79 * @param {object} hycalSettings The calendar settings. 80 * @returns {string} Modified header HTML. 81 */ 82 let headerHtml = hycalHooks.applyFilters( 83 "hycal.tooltipHeader", 84 ` 85 <button class="hycal-tooltip-close" aria-label="Close" type="button" style="position: absolute; top: 8px; right: 8px; background: none; border: none; font-size: 24px; cursor: pointer; padding: 0; line-height: 1; color: inherit; opacity: 0.7;"> 86 <span aria-hidden="true">×</span> 87 </button> 88 <h2 class="hycal-event-title">${eventTitle} </h2> 89 <p class="hycal-event-time"><span class="hycal-event-start-time">${startTime}</span><span class="hycal-event-end-time">${endTime}</span></p> 90 ${locString}`, 91 info, 92 hycalSettings 93 ); 94 95 let toolContent = headerHtml; 96 97 const description = hycal_breakify( 98 hycal_urlify(info.event.extendedProps.description) 99 ); 100 101 /** 102 * Filter: hycal.tooltipDescription 103 * 104 * Filter the tooltip description HTML. 105 * 106 * @since 1.0.0 107 * 108 * @param {string} descriptionHtml The description HTML. 109 * @param {object} info FullCalendar event info object. 110 * @param {object} hycalSettings The calendar settings. 111 * @returns {string} Modified description HTML. 112 */ 113 const descriptionHtml = hycalHooks.applyFilters( 114 "hycal.tooltipDescription", 115 description 116 ? `<div class="hycal-event-description">${description}</div>` 117 : "", 118 info, 119 hycalSettings 120 ); 121 122 toolContent += descriptionHtml; 123 124 const mapHtml = location ? hycal_mapify(location) : "";
125 const addToGoogleHtml = info.event.url 126 ? hycal_addToGoogle(info.event.url) 127 : ""; 128 const openEventHtml = hycal_openEventLink(info.event); 129 const downloadICSHtml = hycal_downloadEventICS(info.event); 130 131 /** 132 * Filter: hycal.tooltipActions 133 * 134 * Filter the array of action buttons in the tooltip. 135 * Add, remove, or modify action buttons (Map, Add to Google, Open Event, Download ICS). 136 * 137 * @since 1.0.0 138 * 139 * @param {array} actions Array of HTML strings for action buttons. 140 * @param {object} info FullCalendar event info object. 141 * @param {object} hycalSettings The calendar settings. 142 * @returns {array} Modified array of action HTML strings. 143 */ 144 let actions = hycalHooks.applyFilters( 145 "hycal.tooltipActions", 146 [mapHtml, addToGoogleHtml, openEventHtml, downloadICSHtml], 147 info, 148 hycalSettings 149 ); 150 151 const actionsHtml = actions.filter(Boolean).join(" "); 152 153 if (actionsHtml) { 154 toolContent += `<div class="toolloc hycal-event-actions">${actionsHtml}</div>`; 155 } 156 157 /** 158 * Filter: hycal.tooltipContent 159 * 160 * Filter the complete tooltip content before rendering. 161 * This is the final filter for tooltip HTML. 162 * 163 * @since 1.0.0 164 * 165 * @param {string} toolContent The complete tooltip HTML. 166 * @param {object} info FullCalendar event info object. 167 * @param {object} hycalSettings The calendar settings. 168 * @returns {string} Modified tooltip HTML. 169 */ 170 toolContent = hycalHooks.applyFilters( 171 "hycal.tooltipContent", 172 toolContent, 173 info, 174 hycalSettings 175 ); 176 177 /** 178 * Filter: hycal.tippyOptions 179 * 180 * Filter the Tippy.js options before creating the tooltip. 181 * Use this to customize tooltip behavior (placement, theme, etc.). 182 * 183 * @since 1.0.0 184 * 185 * @param {object} options The Tippy.js options object. 186 * @param {object} info FullCalendar event info object. 187 * @param {object} hycalSettings The calendar settings. 188 * @returns {object} Modified Tippy.js options. 189 */ 190 const tippyOptions = hycalHooks.applyFilters( 191 "hycal.tippyOptions", 192 { 193 trigger: "click", 194 content: toolContent, 195 theme: "light", 196 allowHTML: true, 197 placement: hycal_is_mobile() ? "bottom" : "auto", 198 popperOptions: hycal_is_mobile() 199 ? { 200 modifiers: [ 201 { 202 name: "flip", 203 enabled: false, 204 options: {}, 205 }, 206 ], 207 } 208 : "", 209 interactive: "true", 210 appendTo: document.getElementById(currCal), 211 maxWidth: 600, 212 boundary: "window", 213 onShow(instance) { 214 // Add popup class to tooltip for styling 215 if (popupClass) { 216 instance.popper.classList.add(popupClass); 217 } 218 // Attach close button handler when tooltip is shown 219 const closeBtn = instance.popper.querySelector(".hycal-tooltip-close"); 220 if (closeBtn) { 221 const handleCloseClick = (e) => { 222 e.stopPropagation(); 223 instance.hide(); 224 }; 225 closeBtn.addEventListener("click", handleCloseClick); 226 closeBtn._hycalCloseHandler = handleCloseClick; 227 } 228 229 /** 230 * Action: hycal.tooltipShow 231 * 232 * Fires when a tooltip is shown. 233 * 234 * @since 1.0.0 235 * 236 * @param {object} instance The Tippy.js instance. 237 * @param {object} info FullCalendar event info object. 238 * @param {object} hycalSettings The calendar settings. 239 */ 240 hycalHooks.doAction("hycal.tooltipShow", instance, info, hycalSettings); 241 }, 242 onHide(instance) { 243 // Remove close button handler when tooltip is hidden 244 const closeBtn = instance.popper.querySelector(".hycal-tooltip-close"); 245 if (closeBtn && closeBtn._hycalCloseHandler) { 246 closeBtn.removeEventListener("click", closeBtn._hycalCloseHandler); 247 delete closeBtn._hycalCloseHandler; 248 } 249 250 /** 251 * Action: hycal.tooltipHide 252 * 253 * Fires when a tooltip is hidden. 254 * 255 * @since 1.0.0 256 * 257 * @param {object} instance The Tippy.js instance. 258 * @param {object} info FullCalendar event info object. 259 * @param {object} hycalSettings The calendar settings. 260 */ 261 hycalHooks.doAction("hycal.tooltipHide", instance, info, hycalSettings); 262 }, 263 }, 264 info, 265 hycalSettings 266 ); 267 268 tippy(info.el, tippyOptions); 269}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.