Hooks
Calendaria fires the hooks below. Register them with Hooks.on() like any core Foundry hook.
Lifecycle hooks
Section titled “Lifecycle hooks”calendaria.init
Section titled “calendaria.init”Fires during Foundry’s init hook, after the CALENDARIA global namespace is created.
Parameters: None
calendaria.ready
Section titled “calendaria.ready”Fires during Foundry’s ready hook, after every Calendaria manager is initialized and before any Calendaria application renders. Register widgets and configure integrations here.
| Parameter | Type | Description |
|---|---|---|
data.api | CalendariaAPI | The public API object |
data.calendar | CalendariaCalendar|null | The active calendar |
data.version | string | Module version |
Hooks.on('calendaria.ready', ({ api, calendar, version }) => { console.log(`Calendaria v${version} ready with calendar: ${calendar?.id}`);});calendaria.rendered
Section titled “calendaria.rendered”Fires at the end of Calendaria’s ready handler, once the show call has been issued for every application configured to appear on load. Those renders are asynchronous and are not awaited, so the elements are not guaranteed to be in the DOM yet. To touch BigCal’s DOM, listen for calendaria.renderCalendar.
Parameters: None
Render hooks
Section titled “Render hooks”calendaria.preRenderCalendar
Section titled “calendaria.preRenderCalendar”Fires before BigCal renders.
| Parameter | Type | Description |
|---|---|---|
data.app | BigCal | The BigCal application instance |
data.displayMode | string | "month", "week", or "year" |
data.calendar | CalendariaCalendar | Active calendar |
calendaria.renderCalendar
Section titled “calendaria.renderCalendar”Fires after BigCal renders and all DOM setup is complete.
| Parameter | Type | Description |
|---|---|---|
data.app | BigCal | The BigCal application instance |
data.element | HTMLElement | The rendered application element |
data.displayMode | string | "month", "week", or "year" |
data.calendar | CalendariaCalendar | Active calendar |
Hooks.on('calendaria.renderCalendar', (data) => { const dayCell = data.element.querySelector('.calendar-day.today'); if (dayCell) dayCell.classList.add('my-module-highlight');});Calendar hooks
Section titled “Calendar hooks”calendaria.calendarSwitched
Section titled “calendaria.calendarSwitched”Fires when the active calendar changes. It also fires once at startup, from inside CalendarManager.initialize(). That happens before calendaria.ready, so a listener registered in calendaria.ready will not see the startup fire. Read the active calendar from the calendaria.ready payload instead.
| Parameter | Type | Description |
|---|---|---|
id | string | Calendar ID |
calendar | CalendariaCalendar | Calendar instance |
calendaria.remoteCalendarSwitch
Section titled “calendaria.remoteCalendarSwitch”Fires when a calendarSwitch socket message arrives. Calendaria does not send that message. Switching the active calendar writes a world setting flagged requiresReload, so other clients reload rather than switching live. The hook fires only if another module calls CALENDARIA.socket.emitCalendarSwitch(calendarId).
| Parameter | Type | Description |
|---|---|---|
id | string | Calendar ID |
calendar | CalendariaCalendar | Calendar instance |
calendaria.calendarAdded
Section titled “calendaria.calendarAdded”Fires when a calendar is created or imported.
| Parameter | Type | Description |
|---|---|---|
id | string | Calendar ID |
calendar | CalendariaCalendar | Calendar instance |
calendaria.calendarUpdated
Section titled “calendaria.calendarUpdated”Fires when a calendar is modified.
| Parameter | Type | Description |
|---|---|---|
id | string | Calendar ID |
calendar | CalendariaCalendar | Updated calendar instance |
calendaria.calendarRemoved
Section titled “calendaria.calendarRemoved”Fires when a calendar is deleted.
| Parameter | Type | Description |
|---|---|---|
id | string | Calendar ID |
Time hooks
Section titled “Time hooks”In previous and current, year is the displayed year, with the calendar’s yearZero already applied. The other components match Foundry’s raw time components.
The Set Date dialog has a Skip Event Triggers option. A jump made with it enabled still fires calendaria.dateTimeChange and the day, month, year, and season hooks. It suppresses the solar threshold hooks, calendaria.moonPhaseChange, calendaria.restDayChange, calendaria.eventTriggered, and calendaria.eventDayChanged for that jump.
calendaria.dateTimeChange
Section titled “calendaria.dateTimeChange”Fires on every world time change. This is the primary hook for time tracking.
| Parameter | Type | Description |
|---|---|---|
data.previous | object | Previous time components: year, month, dayOfMonth, hour, minute, second |
data.current | object | Current time components |
data.diff | number | Time delta in seconds |
data.calendar | CalendariaCalendar | Active calendar |
data.worldTime | number | Current world time in seconds |
calendaria.dayChange
Section titled “calendaria.dayChange”Fires when the day changes.
| Parameter | Type | Description |
|---|---|---|
data.previous | object | Previous time components |
data.current | object | Current time components |
data.calendar | CalendariaCalendar | Active calendar |
calendaria.monthChange
Section titled “calendaria.monthChange”Fires when the month changes. The payload matches calendaria.dayChange.
calendaria.yearChange
Section titled “calendaria.yearChange”Fires when the year changes. The payload matches calendaria.dayChange.
calendaria.seasonChange
Section titled “calendaria.seasonChange”Fires when the season changes.
| Parameter | Type | Description |
|---|---|---|
data.previous | object | Previous time components |
data.current | object | Current time components |
data.calendar | CalendariaCalendar | Active calendar |
data.previousSeason | object|null | Previous season definition |
data.currentSeason | object|null | Current season definition |
calendaria.remoteDateChange
Section titled “calendaria.remoteDateChange”Fires when a dateChange socket message arrives from another client. Calendaria never sends that message, because world time already reaches every client through Foundry’s own updateWorldTime hook. This fires only if another module calls CALENDARIA.socket.emitDateChange(worldTime, delta). For ordinary time tracking, use calendaria.dateTimeChange.
| Parameter | Type | Description |
|---|---|---|
data.worldTime | number | New world time in seconds |
data.delta | number | Time delta in seconds |
Solar hooks
Section titled “Solar hooks”calendaria.sunrise, calendaria.sunset, calendaria.midnight, and calendaria.midday fire when the matching time-of-day threshold is crossed. They fire only when time moves forward. Rewinding the clock fires none of them. A forward jump replays each crossing it passed, capped at 30 intermediate days, so a longer jump fires fewer times than the number of days skipped.
All four take the same payload.
| Parameter | Type | Description |
|---|---|---|
data.worldTime | number | World time in seconds |
data.components | object | Time components |
data.calendar | CalendariaCalendar | Active calendar |
Moon hooks
Section titled “Moon hooks”calendaria.moonPhaseChange
Section titled “calendaria.moonPhaseChange”Fires when any moon’s phase changes.
| Parameter | Type | Description |
|---|---|---|
data.moons | object[] | The moons whose phase changed |
data.calendar | CalendariaCalendar | Active calendar |
data.worldTime | number | World time in seconds |
Each entry in data.moons has these fields.
| Field | Type | Description |
|---|---|---|
moonIndex | number | Index of the moon |
moonName | string | Localized moon name |
visible | boolean | Whether the moon is visible to the current user. Always true for a GM |
previousPhaseIndex | number | Previous phase index |
previousPhaseName | string|null | Previous phase name |
currentPhaseIndex | number | Current phase index |
currentPhaseName | string|null | Current phase name |
Rest day hooks
Section titled “Rest day hooks”calendaria.restDayChange
Section titled “calendaria.restDayChange”Fires when the date moves onto or off a rest day.
| Parameter | Type | Description |
|---|---|---|
data.isRestDay | boolean | Current rest day status |
data.wasRestDay | boolean | Previous rest day status |
data.weekday | object|null | Weekday info: index, name, abbreviation |
data.worldTime | number | World time in seconds |
data.calendar | CalendariaCalendar | Active calendar |
Clock hooks
Section titled “Clock hooks”calendaria.clockStartStop
Section titled “calendaria.clockStartStop”Fires when the real-time clock starts or stops.
| Parameter | Type | Description |
|---|---|---|
data.running | boolean | Whether the clock is running |
data.increment | number | Time increment in game seconds |
data.locked | boolean | Present only when fired from the lock toggle |
data.disabled | boolean | Present only when fired by a change to the disabled state |
calendaria.clockUpdate
Section titled “calendaria.clockUpdate”Fires when clock state arrives from another client, which is how the real-time clock stays in sync across connected clients.
| Parameter | Type | Description |
|---|---|---|
data.running | boolean | Whether the clock is running |
data.ratio | number | The clock’s selected time increment in game seconds, the same value calendaria.clockStartStop reports as increment |
calendaria.visualTick
Section titled “calendaria.visualTick”Fires once per real second while the real-time clock is running. It does not fire while the clock is stopped or blocked by combat. The HUD, BigCal, MiniCal, Time Keeper, and Stop Watch listen for it to update their time displays.
| Parameter | Type | Description |
|---|---|---|
data.predictedWorldTime | number | Predicted world time in seconds. Interpolation can put it ahead of game.time.worldTime |
calendaria.worldTimeUpdated
Section titled “calendaria.worldTimeUpdated”Fires from Calendaria’s updateWorldTime handler with the raw world time and delta. It fires after calendaria.dateTimeChange and before calendaria.eventTriggered.
| Parameter | Type | Description |
|---|---|---|
worldTime | number | Current world time in seconds |
dt | number | Time delta in seconds |
Stop Watch hooks
Section titled “Stop Watch hooks”The stop watch is per-client state, so these hooks fire only on the client whose stop watch changed.
calendaria.stopwatchStart
Section titled “calendaria.stopwatchStart”Fires when the stop watch starts.
| Parameter | Type | Description |
|---|---|---|
data.mode | string | "realtime" or "gametime" |
calendaria.stopwatchPause
Section titled “calendaria.stopwatchPause”Fires when the stop watch is paused.
| Parameter | Type | Description |
|---|---|---|
data.mode | string | Stop watch mode |
data.elapsed | number | Elapsed time, in milliseconds for realtime and seconds for gametime |
calendaria.stopwatchReset
Section titled “calendaria.stopwatchReset”Fires when the stop watch is reset.
| Parameter | Type | Description |
|---|---|---|
data.mode | string | Stop watch mode |
calendaria.stopwatchLap
Section titled “calendaria.stopwatchLap”Fires when a lap is recorded.
| Parameter | Type | Description |
|---|---|---|
data.mode | string | Stop watch mode |
data.lap | number | Lap number |
data.elapsed | number | Elapsed time at lap |
Note hooks
Section titled “Note hooks”calendaria.noteCreated and calendaria.noteUpdated both pass a single note stub.
| Field | Type | Description |
|---|---|---|
id | string | Journal page ID |
uuid | string | Page UUID |
name | string | Note name |
content | string | Page text content |
flagData | object | The note’s calendar data |
calendarId | string | Calendar the note belongs to |
journalId | string|null | Parent journal entry ID |
visible | boolean | Whether the current user may observe the note |
isOwner | boolean | Whether the current user owns the note |
ownership | object | Ownership record from the parent journal |
calendaria.noteCreated
Section titled “calendaria.noteCreated”Fires when a calendar note is created.
calendaria.noteUpdated
Section titled “calendaria.noteUpdated”Fires when a calendar note is modified.
calendaria.noteDeleted
Section titled “calendaria.noteDeleted”Fires when a calendar note is deleted.
| Parameter | Type | Description |
|---|---|---|
pageId | string | Journal page ID |
calendaria.presetsChanged
Section titled “calendaria.presetsChanged”Fires when note presets are added, removed, or modified.
| Parameter | Type | Description |
|---|---|---|
presets | object[] | Updated array of all presets |
Event hooks
Section titled “Event hooks”Both event hooks are evaluated by the scheduler, which runs only on the primary GM’s client. Player clients never receive them. To reach players, broadcast from the GM listener or use calendaria.reminderReceived.
calendaria.eventTriggered
Section titled “calendaria.eventTriggered”Fires when a scheduled event or reminder occurs.
| Parameter | Type | Description |
|---|---|---|
data.id | string | Note or event ID |
data.name | string | Event name |
data.flagData | object | Event calendar data |
data.currentDate | object | Current date components, events only |
data.reminderType | string | Reminder type, reminders only |
data.isReminder | boolean | True if this is a reminder |
calendaria.eventDayChanged
Section titled “calendaria.eventDayChanged”Fires when a multi-day event progresses to a new day.
| Parameter | Type | Description |
|---|---|---|
data.id | string | Note ID |
data.name | string | Event name |
data.progress | object | currentDay, totalDays, percentage, isFirstDay, isLastDay |
Reminder hooks
Section titled “Reminder hooks”calendaria.reminderReceived
Section titled “calendaria.reminderReceived”Fires when a reminder notification arrives from another client. ReminderScheduler listens for it to display the notification, and it is available for module integration.
| Parameter | Type | Description |
|---|---|---|
data.type | string | "toast" or "dialog" |
data.noteId | string | Journal page ID |
data.noteName | string | Note name |
data.journalId | string | Parent journal entry ID |
data.message | string | Formatted reminder message |
data.icon | string|null | Icon identifier |
data.iconType | string|null | Icon type, such as "fontawesome" |
data.color | string|null | Icon color |
data.targets | string[] | User IDs who should receive the reminder |
Hooks.on('calendaria.reminderReceived', (data) => { if (data.targets.includes(game.user.id)) { console.log(`Reminder: ${data.noteName}`); }});Condition hooks
Section titled “Condition hooks”calendaria.conditionEvaluated
Section titled “calendaria.conditionEvaluated”Fires after a note’s condition tree is evaluated through the API. Passing { silent: true } to evaluateNote() skips the hook, which avoids flooding listeners when evaluating a note across many dates in a loop.
| Parameter | Type | Description |
|---|---|---|
pageId | string | Journal entry page ID |
date | object | Date the note was evaluated against |
result | boolean | Evaluation result |
Fog of War hooks
Section titled “Fog of War hooks”calendaria.fogRangeChanged
Section titled “calendaria.fogRangeChanged”Fires when you reveal or reset fog of war date ranges.
| Parameter | Type | Description |
|---|---|---|
data.calendarId | string | Calendar the ranges belong to |
data.ranges | object[] | Updated array of revealed date ranges |
Cinematic hooks
Section titled “Cinematic hooks”calendaria.cinematicStart fires when a cinematic time skip begins and calendaria.cinematicEnd when it completes. calendaria.cinematicAbort fires when a user cancels the skip. calendaria.cinematicPause and calendaria.cinematicResume fire around a paused skip.
All five receive the same payload.
| Parameter | Type | Description |
|---|---|---|
data.startTime | number | World time in seconds at the start of the skip |
data.endTime | number | World time in seconds at the end of the skip |
data.deltaSeconds | number | Length of the skip in seconds |
data.calendarId | string|null | Active calendar ID |
data.keyframes | object[] | The keyframes the cinematic plays through |
data.settings | object | Snapshot of the cinematic settings in force for this skip |
Weather hooks
Section titled “Weather hooks”calendaria.weatherChange
Section titled “calendaria.weatherChange”Fires when weather changes. The payload shape varies by source. A per-zone change carries previous, current, and zoneId. A bulk change carries only bulk. An editor preview carries only visualOnly.
The hook also fires when a scene is activated, reporting the zone’s existing weather so listeners can re-apply effects for the new scene. On that path and on remote changes, previous is null even when earlier weather existed. Compare against state you cached rather than relying on previous.
| Parameter | Type | Description |
|---|---|---|
data.previous | object|null | Previous weather state |
data.current | object|null | Current weather state |
data.zoneId | string|undefined | Climate zone ID for the change |
data.remote | boolean | True if the change originated on another client |
data.visualOnly | boolean | True when fired from a Weather Editor preview. FX and sound handlers should skip it |
data.bulk | boolean | True when the change affects all zones at once. previous, current, and zoneId are absent, so re-read weather state from the API |
Hooks.on('calendaria.weatherChange', (data) => { if (data.bulk) return refreshAllZones(); if (data.current) applyWeather(data.zoneId, data.current);});calendaria.weatherPeriodChange
Section titled “calendaria.weatherPeriodChange”Fires when the intraday weather period changes at a solar threshold. It fires only on the primary GM’s client, and only while intraday weather generation is enabled. A bulk calendaria.weatherChange for the same transition always precedes it.
| Parameter | Type | Description |
|---|---|---|
data.period | string | The period that just started: "night", "morning", "afternoon", or "evening" |
Import hooks
Section titled “Import hooks”calendaria.importStarted
Section titled “calendaria.importStarted”Fires when a calendar import begins.
| Parameter | Type | Description |
|---|---|---|
data.importerId | string | Importer ID |
data.calendarId | string | Target calendar ID |
calendaria.importComplete
Section titled “calendaria.importComplete”Fires when an import finishes successfully.
| Parameter | Type | Description |
|---|---|---|
data.importerId | string | Importer ID |
data.calendarId | string | Created calendar ID |
data.calendar | CalendariaCalendar | Imported calendar |
calendaria.importFailed
Section titled “calendaria.importFailed”Fires when an import fails.
| Parameter | Type | Description |
|---|---|---|
data.importerId | string | Importer ID |
data.calendarId | string | Target calendar ID |
data.error | string | Error message |
Display hooks
Section titled “Display hooks”calendaria.displayFormatsChanged
Section titled “calendaria.displayFormatsChanged”Fires when display format settings are saved.
| Parameter | Type | Description |
|---|---|---|
newFormats | object | Updated display format configuration |
Theming runs through 3DS:ATLAS. Calendaria listens for the 3ds-atlas.themeChanged hook and re-renders the HUD, Time Keeper, MiniCal, BigCal, and Stop Watch when its own theme changes. It fires no theme hook of its own.
Widget hooks
Section titled “Widget hooks”calendaria.widgetRegistered
Section titled “calendaria.widgetRegistered”Fires when a widget is registered through the Widget API.
| Parameter | Type | Description |
|---|---|---|
fullId | string | Full widget ID, moduleId.widgetId |
config | object | Widget configuration |
calendaria.widgetsRefresh
Section titled “calendaria.widgetsRefresh”Fires when widgets are re-rendered.
Parameters: None