typograph-editor-documentation
    Preparing search index...

    Typograph — Page Action Events

    This document describes the custom DOM events fired by the Typograph canvas engine when the user performs page-level actions. It is intended for developers who embed the Typograph editor and need to react to changes in the page structure (e.g. to sync a thumbnail strip, update a save state, or push changes to a backend).

    Two events here are not structural changes: typograph_page_shown reports which spread is shown, and typograph_page_hover which page the pointer is over. It is documented alongside the others because it speaks about pages, and in full — with the two accessors that answer which page is selected and which page is the work on — in PageSelection.md.


    All page events are dispatched on document as standard CustomEvent objects. The event payload is available on event.detail.

    document.addEventListener('typograph_page_added', (event) => {
    const { page_index, page_name } = event.detail;
    console.log(`Page "${page_name}" added at index ${page_index}`);
    });

    The page action events pass through the same throttle as all other Typograph custom events. The default limit is 5 events per event-type per second. Because page actions are user-initiated and infrequent this limit is never reached in practice.

    typograph_page_shown and typograph_page_hover are the exceptions: they are not throttled, for the reasons given in their own sections below.

    If your application needs a higher or lower rate you can adjust it after the editor is ready:

    document.addEventListener('typograph_editor_ready', () => {
    typograph.set_custom_event_throttle(10); // max 10 per type per second
    });

    Fired after a new blank page has been appended to the document.

    Property Type Description
    page_index number Zero-based index of the newly added page
    page_name string Name given to the new page
    document.addEventListener('typograph_page_added', (e) => {
    const { page_index, page_name, container_index, record_index } = e.detail;
    });

    Fired after a page has been duplicated. The new page is always appended at the end of the document.

    Property Type Description
    source_index number Zero-based index of the page that was copied
    page_index number Zero-based index of the resulting duplicate
    page_name string Name of the duplicate page
    document.addEventListener('typograph_page_duplicated', (e) => {
    const { source_index, page_index, page_name } = e.detail;
    });

    Fired after a page has been removed from the document.

    Note — page_index is the index the page held before it was deleted. After deletion, all pages at higher indexes shift down by one.

    Property Type Description
    page_index number Zero-based index of the spread the page was in (pre-deletion)
    page_name string Name of the deleted page
    container_index number The same spread index, named the way get_selected_page() names it
    record_index number | null Which page of that spread was deleted; null when the whole spread was

    Deleting one page out of a two-page spread fires this event too, with that page's record_index; the spread itself stays, holding the other page. Before 20261007 only deleting a whole spread fired it.

    document.addEventListener('typograph_page_deleted', (e) => {
    const { page_index, page_name } = e.detail;
    });

    Fired after the user drags a page thumbnail to a new position in the page bar.

    Property Type Description
    from_index number Zero-based index of the page before the move
    to_index number Zero-based index of the page after the move
    document.addEventListener('typograph_page_rearranged', (e) => {
    const { from_index, to_index } = e.detail;
    });

    Fired after a page and all its elements have been scaled. Both dimensions are scaled independently, so non-uniform scaling is possible.

    Property Type Description
    page_index number Zero-based index of the scaled page
    scale_x number Horizontal scale factor (e.g. 2.0 = doubled in width)
    scale_y number Vertical scale factor
    document.addEventListener('typograph_page_scaled', (e) => {
    const { page_index, scale_x, scale_y } = e.detail;
    });

    Fired after a spread page has been split into two independent single pages. The spread is replaced by the two pages at the same position in the document; subsequent pages shift up by one index.

    Property Type Description
    spread_index number Zero-based index the spread occupied before the split
    page_name string Name of the spread page that was split
    document.addEventListener('typograph_spread_split', (e) => {
    const { spread_index, page_name } = e.detail;
    });

    Fired after two adjacent single pages have been merged into a horizontal spread. The right page is removed from the document; the left page becomes the spread and retains its index. Pages that were after the right page shift down by one.

    Property Type Description
    left_index number Zero-based index of the left (surviving) page before the merge
    right_index number Zero-based index of the right page before it was merged in
    document.addEventListener('typograph_pages_merged', (e) => {
    const { left_index, right_index } = e.detail;
    });

    Fired when a different spread is shown on the canvas — whatever showed it: a click in the page bar, set_active_page(), opening a document, or a delete, reorder or undo that moves the view.

    Property Type Description
    container_index number Zero-based index of the spread now shown
    record_indexes number[] Its pages — [0] for a single page, [0, 1] for a facing pair
    page_names string[] The name of each of those pages, in the same order ('' for an unnamed page)
    document.addEventListener('typograph_page_shown', (e) => {
    const { container_index, record_indexes, page_names } = e.detail;
    myPageList.markCurrent(container_index);
    myTitle.textContent = page_names.filter(Boolean).join(' / ');
    });

    It fires once per change and never for a redraw that keeps the same spread — zooming, scrolling, editing or an undo on the spread already shown report nothing. Opening a document always reports the spread it opens on, even when it is the same document again, so a host can set its own state from this one event. While a cover's spine is edited upright (below) nothing is reported: it is still the same page to the host.

    Like typograph_page_hover it is not throttled: each event is a real change, and dropping one would leave your UI showing the wrong page.

    The pair container_index + record_indexes addresses pages the way typograph.get_selected_page(), logical_pages() and move_logical_page() do — see PageSelection.md. To ask at any moment rather than listen, typograph.get_focused_page() answers which spread is shown.


    Fired when the page under the pointer changes, on the rendered spread in the canvas — not on the page bar.

    Property Type Description
    container_index number | null Zero-based index of the spread under the pointer; null when the pointer is over no page
    record_index number | null Which page within that spread — 0 or 1 for a facing pair; null when over no page
    document.addEventListener('typograph_page_hover', (e) => {
    const { container_index, record_index } = e.detail;
    if (record_index === null) clearPageHighlight();
    else highlightPage(container_index, record_index);
    });

    Both fields are null together, and that is a real state rather than a failure: the pointer can be over the canvas without being over paper — the grey around the spread, or the gutter between two pages.

    It fires once per boundary crossing, not continuously while the pointer stays on one page. Like typograph_pageelement_hover — and unlike every other event in this document — it is not throttled: the change detection already limits it to one event per crossing, and each one is a meaningful transition.

    Off by default in a view-only embed. Hover dispatch follows set_hover_events() and is deliberately independent of interactive / set_interactive(), so a viewer host can drive a layout picker or a page highlight without making the document editable: typograph.set_hover_events(true).

    ⚠️ Element hover and page hover are independent. A page can have no element on it, and an element can overhang the paper onto the grey — do not infer one from the other.

    ⚠️ The pair addresses a page the way logical_pages(), move_logical_page() and delete_logical_page() do. The other page events in this document carry a flat page_index instead; the two are not interchangeable. See PageSelection.md for converting between them.


    A cover's spine was opened for editing upright, and later closed (TYP-783). Page → Edit spine, or a double-click on an empty part of the spine, opens it; OK / Cancel above the spine, the same two buttons in the Spine panel, or Escape closes it.

    Event Property Type Description
    …_started container_index number The cover's index in the document's spreads
    spine_direction 'top_to_bottom' | 'bottom_to_top' Which way the spine reads, and so which way it was turned
    …_ended container_index number As above
    outcome 'ok' | 'cancel' OK wrote the spine into the cover as one undo step; Cancel left the cover as it was
    document.addEventListener('typograph_spine_edit_started', () => myToolbar.lockSaving(true));
    document.addEventListener('typograph_spine_edit_ended', () => myToolbar.lockSaving(false));

    ⚠️ Lock your own save and page UI between the two. While the spine is open, the spread at the cover's position is a temporary one — the spine turned on its side — and the cover is held aside. Saving is safe (get_document_data_as_string() writes the held cover in its place), but it saves the cover without the edits made in the session so far, and anything that walks the spreads sees the temporary one. The editor greys its File and Page menus, refuses ⌘S / ⌘O, and locks the page bar; a host's own menu items are greyed too. typograph.get_typograph_document().is_spine_editing() answers at any moment.


    A spread's Keep pages together was turned on or off (TYP-976): from the Page panel's switch, or by the host calling typograph.set_keep_pages_together(container_index, keep).

    Property Type Description
    container_index number The spread's index in the document's spreads
    keep_together boolean true: its pages stay one block through every reorder, delete and facing toggle
    document.addEventListener('typograph_keep_pages_together', (e) => {
    const { container_index, keep_together } = e.detail;
    myLayoutPanel.setLocked(container_index, keep_together);
    });

    typograph.set_keep_pages_together(2, true); // true when applied, false when refused
    typograph.get_keep_pages_together(2); // true / false, or null for a spread that does not exist

    The change is one undo step, so it also fires typograph_document_changed and is_changed() turns true. Turning it off lets the pages pair the way the rest of the document does at once: with facing pages off, a kept-together spread becomes single pages, in the same undo step.

    ⚠️ Not sent when nothing changes:

    • set_keep_pages_together() answers false for a spread that does not exist, for the cover (always one block), and while a spine is being edited;
    • it answers true and sends nothing when the spread already has that setting.

    An undo or redo of the toggle is a structure step like any other, so it fires typograph_document_changed, not this event. Read the state again with get_keep_pages_together() when that fires.


    Event Trigger Key detail properties
    typograph_page_added New blank page appended page_index, page_name
    typograph_page_duplicated Active page duplicated source_index, page_index, page_name
    typograph_page_deleted Page removed page_index, page_name, container_index, record_index
    typograph_page_rearranged Page dragged to new position from_index, to_index
    typograph_page_scaled Page and elements scaled page_index, scale_x, scale_y
    typograph_spread_split Spread split into two pages spread_index, page_name
    typograph_pages_merged Two pages merged into a spread left_index, right_index
    typograph_page_shown A different spread is shown (page bar, navigation, document opened, …) container_index, record_indexes, page_names
    typograph_page_hover Pointer moves onto a different page (or off the paper) container_index, record_index
    typograph_spine_edit_started A cover's spine opened for editing container_index, spine_direction
    typograph_spine_edit_ended The spine session closed container_index, outcome
    typograph_keep_pages_together A spread's Keep pages together turned on or off container_index, keep_together