Skip to content

Commit 1c3d069

Browse files
martinrapavyclaude
andcommitted
Document schedule_list_rendered callback with week-separator example
Adds a new ### schedule_list_rendered entry under Events and callbacks, slotted between schedule_registration_options_loaded and render_course_tile. Covers the { el, schedules, course } argument shape (with el as a plain DOM Element, not jQuery), notes the re-render-on-place-change idempotency requirement, and includes a practical week-separator example that walks the rendered tiles and inserts a section header before each numeric group. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 568a062 commit 1c3d069

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

docs/widgets/registration-widget.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,81 @@ window.ZOOZA = {
875875
};
876876
```
877877

878+
### `schedule_list_rendered`
879+
880+
Fires immediately after the widget renders the schedule list and appends it to the DOM. Use this hook when you need to run your own DOM work over the rendered tile collection — adding badges or section separators, attaching analytics, observing visibility, anything that needs the tiles to already be on the page.
881+
882+
The callback fires on **every** render of the schedule list, including re-renders that follow a place change. Make sure your handler is idempotent — guard against double-attaching listeners or duplicating injected nodes (the practical example below shows the pattern).
883+
884+
#### Params
885+
886+
The callback receives a single object argument with the following attributes:
887+
888+
| Attribute | Description |
889+
|---|---|
890+
| `el` | The `.zooza_schedules` container as a **plain DOM `Element`** (not a jQuery object). Holds the prepended filter and all rendered `.zooza_schedules_schedule[data-schedule_id]` tiles. |
891+
| `schedules` | Array of schedule objects in render order. The array order lines up 1:1 with the rendered tiles, so `schedules[ i ]` matches the i-th tile inside `el`. Each entry exposes the same stable members documented for [`render_schedule_tile`](#render_schedule_tile)'s `schedule` arg (`id`, `get_date_formatted()`, `get_start_formatted()`, `get_end_formatted()`, `get_price()`, `get_capacity_formatted()`). |
892+
| `course` | The currently selected course. Same stable shape as the `course` arg in [`render_course_tile`](#render_course_tile) (`id`, `name`, `description`, `course_type`, `registration_type`, `metadata`). |
893+
894+
:::info `el` is a plain DOM Element
895+
Unlike [`schedule_registration_options_loaded`](#schedule_registration_options_loaded) (which passes `el` as a jQuery object for legacy reasons), `schedule_list_rendered` passes `el` as a plain DOM `Element`. Embedders without jQuery on their page can use it directly — `querySelectorAll`, `insertBefore`, `classList`, etc. If you do have jQuery available, wrap with `$( el )` if you prefer.
896+
:::
897+
898+
##### Minimal example — log every render
899+
900+
```javascript
901+
window.ZOOZA = {
902+
callback: {
903+
schedule_list_rendered: ( { el, schedules, course } ) => {
904+
const tiles = el.querySelectorAll( '.zooza_schedules_schedule' );
905+
console.info( `Rendered ${ tiles.length } schedules for course "${ course.name }"` );
906+
},
907+
},
908+
};
909+
```
910+
911+
##### Practical example — week separators between schedule groups
912+
913+
A common pattern: the schedule list contains several weekly groups whose names start with a numeric prefix (`"1. 22 JUNE - 3 JULY 2026 // 09.00-10.10"`, `"1. 22 JUNE - 3 JULY 2026 // 10.30-11.40"`, …, `"2. 06 JULY - 17 JULY 2026 // 09.00-10.10"`, …). The example below walks the rendered tiles, detects when the leading group number changes, and inserts a separator before the first tile of each new group.
914+
915+
The handler is idempotent: it removes any separators it injected on a previous render before walking the tiles, so a re-render after a place change does not stack duplicates.
916+
917+
```javascript
918+
window.ZOOZA = {
919+
callback: {
920+
schedule_list_rendered: ( { el, schedules } ) => {
921+
// The callback fires on every render (including re-renders after a
922+
// place change), so clear any separators we injected previously.
923+
el.querySelectorAll( '.my-week-separator' ).forEach( ( node ) => node.remove() );
924+
925+
const tiles = el.querySelectorAll( '.zooza_schedules_schedule' );
926+
let last_group = null;
927+
928+
tiles.forEach( ( tile, index ) => {
929+
const schedule = schedules[ index ];
930+
const match = schedule.name && schedule.name.match( /^(\d+)\./ );
931+
if ( ! match ) {
932+
return;
933+
}
934+
935+
const group_number = match[ 1 ];
936+
if ( group_number === last_group ) {
937+
return;
938+
}
939+
last_group = group_number;
940+
941+
const separator = document.createElement( 'div' );
942+
separator.className = 'my-week-separator';
943+
separator.textContent = schedule.name;
944+
tile.parentNode.insertBefore( separator, tile );
945+
} );
946+
},
947+
},
948+
};
949+
```
950+
951+
The widget exposes `schedule.name` on each entry alongside the stable getters listed in [`render_schedule_tile`](#render_schedule_tile) — it is the human-readable label the widget itself uses on the tile.
952+
878953
### `render_course_tile`
879954

880955
Returns the HTML that goes **inside** a single course tile. The widget owns everything else: the `<div class="zooza_courses_course" data-course_id="<id>">` wrapper, the grid layout, the "Select" CTA, the collapse-on-select, and the "back to all courses" affordance. Register this callback when you want a different look for the courses than the built-in default — your own headings, images, marketing copy, prices, badges, anything.

0 commit comments

Comments
 (0)