PageSourceSearch

https://www.gaming.cat/wp-content/plugins/hydrogen-calendar-embeds/public/js/hycal.js?ver=3.0.3

js gaming.cat collected 2026-10-02 12:42:11 UTC 10,056 bytes, 313 lines download raw bytes

1/**
2 * Hydrogen Calendar Embeds - Main Calendar Renderer
3 *
4 * Initializes and renders FullCalendar instances with the plugin's
5 * configuration. Handles view resolution, event sources, and toolbar setup.
6 *
7 * @package hydrogen-calendar-embeds
8 * @since 1.0.0
9 */
10
11function hycal_render_calendar(hycalSettings) {
12  /**
13   * Action: hycal.beforeRender
14   *
15   * Fires before the calendar starts rendering.
16   * Use this to perform setup tasks or modify the DOM.
17   *
18   * @since 1.0.0
19   *
20   * @param {object} hycalSettings The calendar settings.
21   */
22  hycalHooks.doAction("hycal.beforeRender", hycalSettings);
23
24  /**
25   * Filter: hycal.settings
26   *
27   * Filter the calendar settings before processing.
28   * Use this to modify or add custom settings.
29   *
30   * @since 1.0.0
31   *
32   * @param {object} hycalSettings The calendar settings.
33   * @returns {object} Modified settings.
34   */
35  hycalSettings = hycalHooks.applyFilters("hycal.settings", hycalSettings);
36
37  const currCal = `hycal-${hycalSettings["instance_id"]}`;
38  const calendarEl = document.getElementById(currCal);
39  calendarEl.innerHTML = "";
40  let width = window.innerWidth;
41
42  const views = hycal_resolve_views(hycalSettings);
43  const calData = hycal_resolve_cals(hycalSettings);
44  const cals = calData.eventSources;
45
46  // console.table(cals); // DEBUG
47  // console.table(hycalSettings); // DEBUG
48  // console.table(views); // DEBUG
49
50  const toolbarLeft = hycal_is_truthy(hycalSettings["show_today_button"])
51    ? "prev,next today"
52    : "prev,next";
53  const toolbarCenter = hycal_is_truthy(hycalSettings["show_title"])
54    ? "title"
55    : "";
56  const toolbarRight = views.length > 1 ? views.all.join(",") : "";
57
58  let selectedView = views.initial;
59
60  const hycalDefaults = {
61    locale: hycalSettings["locale"],
62
63    eventSources: cals,
64
65    views: {
66      // Options apply to dayGridMonth, dayGridWeek, and dayGridDay views
67      dayGrid: {
68        eventTimeFormat: {
69          hour: "numeric",
70          minute: "2-digit",
71          meridiem: "short",
72        },
73      },
74      // Custom List View - only custom one needs definition
75      listCustom: {
76        type: "list",
77        duration: { days: parseInt(hycalSettings["custom_days"]) },
78        buttonText: hycalSettings["custom_list_button"],
79      },
80    },
81
82    // Day grid options
83    eventDisplay: "block", // Adds border and bocks to events instead of bulleted list (default)
84    height: "auto",
85    fixedWeekCount: false, // True: 6 weeks, false: flex for month
86
87    // List options
88    listDayFormat: { weekday: "long", month: "long", day: "numeric" },
89
90    initialView: views.initial,
91
92    headerToolbar: {
93      left: toolbarLeft,
94      center: toolbarCenter,
95      right: toolbarRight,
96    },
97
98    eventDidMount: function (info) {
99      // Handle free/busy calendars with undefined titles
100      // Google Calendar API returns the string "undefined" for free/busy events
101      if (!info.event.title || info.event.title === "undefined") {
102        info.event.setProp(
103          "title",
104          wp.i18n.__("Busy", "hydrogen-calendar-embeds"),
105        );
106      }
107
108      if (hycalSettings["use_tooltip"] === "true") {
109        hycal_tippyRender(info, currCal, hycalSettings);
110      }
111
112      /**
113       * Action: hycal.eventDidMount
114       *
115       * Fires after each event element is added to the DOM.
116       * Use this to add custom attributes, styles, or behaviors to events.
117       *
118       * @since 1.0.0
119       *
120       * @param {object} info          FullCalendar event info object.
121       * @param {object} hycalSettings The calendar settings.
122       * @param {string} currCal       The calendar container ID.
123       */
124      hycalHooks.doAction("hycal.eventDidMount", info, hycalSettings, currCal);
125    },
126
127    eventClick: function (info) {
128      if (
129        hycalSettings["use_tooltip"] === "true" ||
130        hycalSettings["no_link"] === "true"
131      ) {
132        info.jsEvent.preventDefault(); // Prevent following link
133      }
134    },
135
136    // Handle calendar source loading errors (ICS fetch failures, etc.)
137    eventSourceFailure: function (error) {
138      const details = [];
139      const failureTypes = [];
140      const normalizedError = error || {};
141
142      if (normalizedError.message) {
143        details.push(normalizedError.message);
144
145        const lowerMessage = normalizedError.message.toLowerCase();
146        if (
147          /(failed to fetch|network error|networkerror|dns|socket|timed out|timeout)/.test(
148            lowerMessage,
149          )
150        ) {
151          failureTypes.push("ICS address is unreachable");
152        }
153        if (
154          /malformed|invalid ical|invalid icalendar|parser error|parse error|unable to parse|missing begin:vcalendar/.test(
155            lowerMessage,
156          )
157        ) {
158          failureTypes.push("Malformed ICS feed");
159        }
160        if (/403|unauthorized|forbidden|401|404|not found/.test(lowerMessage)) {
161          failureTypes.push(
162            "REST API endpoint is not public or the remote feed returned an HTTP error",
163          );
164        }
165      }
166
167      if (normalizedError.response) {
168        const code = normalizedError.response.status;
169        const statusText = normalizedError.response.statusText || "";
170        if (code) {
171          details.push(`HTTP ${code}${statusText ? ` ${statusText}` : ""}`);
172          if (code === 401 || code === 403) {
173            failureTypes.push(
174              "REST API endpoint is not public or access is blocked",
175            );
176          } else if (code === 404) {
177            failureTypes.push("REST API endpoint or ICS URL not found");
178          } else if (code >= 500) {
179            failureTypes.push(
180              "Remote calendar service returned a server error",
181            );
182          }
183        }
184      }
185
186      if (normalizedError.error) {
187        details.push(normalizedError.error);
188      }
189
190      if (normalizedError.source && normalizedError.source.url) {
191        details.push(`Source URL: ${normalizedError.source.url}`);
192      }
193
194      const consoleData = {
195        reason: failureTypes.length
196          ? failureTypes.join(" | ")
197          : "Unable to determine failure reason",
198        details: details.length ? details.join(" | ") : "No details available",
199        error: normalizedError,
200      };
201
202      console.error(
203        "Hydrogen Calendar Embeds: Failed to load event source.",
204        consoleData,
205      );
206
207      // Display user-friendly message in calendar container
208      const errorMsg = document.createElement("div");
209      errorMsg.className = "hycal-error";
210      errorMsg.style.cssText =
211        "color: #721c24; background: #f8d7da; padding: 12px; border-radius: 4px; margin: 8px 0;";
212      errorMsg.textContent = wp.i18n.__(
213        "Unable to load calendar data. Please try again later.",
214        "hydrogen-calendar-embeds",
215      );
216      // Only show one error message
217      if (!calendarEl.querySelector(".hycal-error")) {
218        calendarEl.insertBefore(errorMsg, calendarEl.firstChild);
219      }
220    },
221
222    //   // Change view on window resize
223    //   windowResize: function (view) {
224    //     // Catch mobile chrome, which changes window size as nav bar appears
225    //     // so only fire if width has changed.
226    //     if (
227    //       window.innerWidth !== width &&
228    //       views.hasList &&
229    //       views.wantsToEnforceListviewOnMobile
230    //     ) {
231    //       const currentView = calendar.view.type;
232    //       const isCurrentlyListView = currentView.toLowerCase().includes("list");
233
234    //       if (hycal_is_mobile(views.mobileBreakpoint)) {
235    //         // Only switch to list view if not already on one
236    //         if (!isCurrentlyListView) {
237    //           calendar.changeView(views.listView);
238    //         }
239    //       } else {
240    //         // Only switch away from list view if we enforced it
241    //         if (
242    //           isCurrentlyListView &&
243    //           !selectedView.toLowerCase().includes("list")
244    //         ) {
245    //           calendar.changeView(selectedView);
246    //         }
247    //       }
248    //     }
249    //   },
250  };
251
252  // Hide past events if requested
253  if (hycal_is_truthy(hycalSettings["hide_past"])) {
254    const today = new Date();
255    const year = today.getFullYear();
256    const month = String(today.getMonth() + 1).padStart(2, "0");
257    const day = String(today.getDate()).padStart(2, "0");
258    const todayString = `${year}-${month}-${day}`;
259
260    hycalDefaults.validRange = {
261      start: todayString,
262    };
263  }
264
265  let hycalOverrides = {};
266  try {
267    hycalOverrides = JSON.parse(hycalSettings["fc_args"]);
268  } catch (e) {
269    console.error("Hydrogen Calendar Embeds: Invalid JSON in fc_args", e);
270  }
271  let hycalArgs = hycal_argmerge(hycalDefaults, hycalOverrides);
272
273  /**
274   * Filter: hycal.fullcalendarOptions
275   *
276   * Filter the FullCalendar options before initialization.
277   * Use this to modify any FullCalendar configuration.
278   *
279   * @since 1.0.0
280   *
281   * @param {object} hycalArgs      The merged FullCalendar options.
282   * @param {object} hycalSettings  The calendar settings.
283   * @param {object} hycalDefaults  The default options.
284   * @returns {object} Modified FullCalendar options.
285   */
286  hycalArgs = hycalHooks.applyFilters(
287    "hycal.fullcalendarOptions",
288    hycalArgs,
289    hycalSettings,
290    hycalDefaults,
291  );
292
293  // console.log(hycalSettings["fc_args"]); // DEBUG
294  // console.log(JSON.stringify(hycalDefaults, null, 2)); // DEBUG
295  // console.log(JSON.stringify(hycalArgs, null, 2)); // DEBUG
296
297  const calendar = new FullCalendar.Calendar(calendarEl, hycalArgs);
298  calendar.render();
299
300  /**
301   * Action: hycal.afterRender
302   *
303   * Fires after the calendar has rendered.
304   * Use this to access the FullCalendar instance or modify the rendered calendar.
305   *
306   * @since 1.0.0
307   *
308   * @param {object} calendar       The FullCalendar instance.
309   * @param {object} hycalSettings  The calendar settings.
310   * @param {Element} calendarEl    The calendar DOM element.
311   */
312  hycalHooks.doAction("hycal.afterRender", calendar, hycalSettings, calendarEl);
313}

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.