PageSourceSearch

https://hzg.berlin/wp-content/plugins/hydrogen-calendar-embeds/public/js/tippy.js?ver=3.0.3

js hzg.berlin collected 2026-10-10 00:58:51 UTC 8,806 bytes, 269 lines download raw bytes

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">&times;</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.