Skip to main content
decktalk-runtime.js is the script that plays a DeckTalk page. It mounts the steps of a scene and makes elements appear on their cues. This page lists its modes, URL parameters, functions, data attributes, fields, CSS hooks, and warnings. The page contract explains how the parts work together. Include the runtime before the scene definitions. After you upgrade DeckTalk, run decktalk runtime to refresh the project’s copy.
deck/index.html

Modes

The URL picks the mode. In prose these docs write index mode, autoplay, cue mode, and freeze mode. Note: step wins over scene and beats. With beats and no registered scene, the scene that owns the earliest cue plays. Cue ownership gives the ownership and mount rules of cue mode.

URL parameters

Note: An unknown scene shows the index with the note unknown scene N. An unknown step shows the index with the note unknown step ID. Neither adds a warning. The catalog still exists, so the recorder records the index with no PAGE ERROR. Note: The runtime sorts the beats pairs by time and splits each pair at its last @. It skips a pair whose seconds are not a number. Write every pair as id@seconds. Note: The recorder builds words from build/audio/timeline.json, in seconds after the section start. It removes commas and @ from each word. It builds prevwords the same way from the section before, and leaves it out for the first section or when the section before has no words. Note: In freeze mode, the step’s cues fire in autoplay order. A cue in a cues list, with no seconds, fires after the timed cues. Animations take no time. A count-up shows its final value, a typewriter shows its full text, and a data-sync element shows whole. Note: With cue or before, only the cues that fire run their handlers. A cue or before id that is not one of the step’s cues adds the warning cue "ID" is not one of step STEP's cues, and every cue fires. enter still gets ctx.frozen as true, so a figure that enter draws in its end state shows that state at every cue. A cue that is not one of the step’s cues adds a warning, and the whole step freezes. In the scaffold, ?step=2.1&cue=2.1aloud shows the script card and the waveform with its word times. It hides the outlines that join the cue word to its drawing, which wait for 2.1word, and the arrow to the slide card, which waits for 2.1follows. decktalk shots --step 2.1 --cue 2.1aloud opens that URL.

DeckTalk.scene(id, definition)

DeckTalk.scene registers a scene and returns DeckTalk, so calls chain. The scenes start on DOMContentLoaded when at least one scene is registered.

Scene fields

Note: A push lasts the autoplay total in autoplay, or the last cue time plus 8 s in cue mode. It lasts at least 4 s. Freeze mode shows no push. Add a camera push says when to use one.

Step fields

Note: In autoplay, a data-cue element appears at its data-at time, or when the cues object fires its cue, whichever comes first. data-at defaults to 0. So a browser preview shows the element as soon as its step mounts. Note: In autoplay, a time in cues at or past hold adds a warning, because that cue fires after the next step mounts. The last step of a scene never warns. A seconds value that is not a number counts as 0. Note: render gets the runtime’s own scene and step objects. Inside its template literal, write every backslash twice (data-tex). Note: enter gets the handler context with id and step set to the step id, and at set to the mount time. Keep the state that cue handlers need on the slide element, as in slide.fig = setup(slide, ctx.frozen). An exception in enter goes to console.error, and the scene goes on.

Handler context

A step’s enter, its on[id] handlers, and every DeckTalk.on(id, fn) handler get two arguments. The first is the slide element of the mounted step. The second is a context object with these fields. A handler that takes no arguments still works.
deck/index.html

DeckTalk methods and properties

Note: A handler that DeckTalk.on registers also stops the unknown cue id warning for its id. Call DeckTalk.start() yourself only for a scene that you register after DOMContentLoaded.

Data attributes

Put these attributes on elements inside the HTML of a step. Note: In cue mode, a data-cue that ?beats= does not list adds a warning. That element appears at its data-at time. In freeze mode, every element appears at once, except elements of cues after the cue parameter. Note: data-count, data-type, and data-sync run when their element appears. Each one needs data-cue or data-at on the same element. Without either, the effect never runs, and the page warns. Note: data-count keeps the decimal places and thousands commas of the number, so 1,250.5 counts with one decimal and a comma. The rest of the text stays in place. The count eases out over data-dur, or 0.9 s. data-type keeps the element at the size of its finished text, so nothing around it moves.

data-fx

Choose a reveal effect says where each effect works well.

data-sync

An element with data-sync shows its words one at a time, each at the moment the voice says it. These rules apply:
  1. The element also needs data-cue or data-at. Without either, the words never sync, and the page warns.
  2. The text must match the spoken words, word for word. Matching ignores case and every character except a to z and 0 to 9.
  3. Apostrophes do not count in this match. The beats stage keeps apostrophes when it matches a cue phrase.
  4. If the text occurs more than once, the runtime uses the first match that starts at most 1.5 s before the element appears. If every match starts earlier, it uses the last match.
  5. If nothing matches, the element appears whole, and the page warns.
  6. Each word appears 20 ms before its start time, with a 0.12 s fade.
  7. The element gets data-fx="none" unless it sets its own data-fx. A reveal effect on the whole element would hide the timing of the words.
  8. Without a words parameter, as in a browser preview, the element appears whole. It also appears whole in freeze mode.

data-tex

The runtime typesets the value of data-tex with KaTeX when window.katex exists. The typeset math replaces the element’s text. Without KaTeX, the text stays, so write it as a readable fallback. KaTeX shows a TeX string that it cannot parse in red, and the page warns. Inside a render template literal, write every backslash twice. JavaScript reads \f, \t, \u, and \x as escapes. For example, \frac becomes a form feed, and \theta becomes a tab. \underbrace and \xrightarrow become syntax errors, and a syntax error blanks the page.
deck/index.html
If a step mounts a data-tex element and KaTeX is missing, the runtime checks again 5 s later. If the element is still plain text, the page warns.

window.__decktalk

window.__decktalk holds read-only state for the recorder, decktalk shots, and your own tools. Note: After a recording, the recorder reads catalog, warnings, frameGaps, syncLog, cueLog, and longFrames. A missing or empty catalog is a page error. decktalk shots reads catalog to find every step. Note: With a numeric t0, the clock starts at load, so narration t=0 is where now() equals t0. With t0=signal, now() counts from narration t=0. Note: In frameGaps, at is the value of now() when the gap ended. A gap under the cover has at equal to -Infinity, and the sidecar field frame_gaps writes it as null. Only the part of a gap after t=0 counts toward STALLED (decktalk check). So a page can do slow first work before t=0, such as drawing a canvas figure or a large SVG. Note: In syncLog, text is the first 24 characters of the text. cueAt is the time the element appeared, and runAt is the start of its first matched word. n is the number of words, and firstOn is the time the first word appeared. The sidecar field is sync_log. Note: In cueLog, every time is in seconds on the narration clock. due is the cue’s time, and ran is when the runtime fired it. frame is the start of the animation frame that fired it, and next and after are the starts of the two frames after it. A cue with ran well past due was held up before its frame. A cue that ran on time but whose next frame started late was held up while its frame was drawn. The sidecar field is cue_log. Note: In longFrames, start, render, and presented are seconds on the narration clock, and ms is the frame’s length. presented is when Chromium showed the frame, or null when the browser does not report it. The sidecar field is long_frames. The runtime also sets document.body.dataset.done to "1" when the last step has mounted.

window.__sceneReady

window.__sceneReady is a Promise. The recorder awaits it before it starts the clock. If the page has not set it, the runtime sets it when the mode starts. The default Promise waits for two things, in order:
  1. document.fonts.ready.
  2. KaTeX, when the document has a [data-tex] element or a <script> whose src contains katex. The runtime checks for window.katex every 100 ms, for up to 5 s. Then it typesets the mounted slide. If KaTeX never loads, the page warns, and the elements keep their text.
In freeze mode, the step has mounted before the wait starts. In cue mode and autoplay, no step has mounted yet, because steps mount on the clock. The recorder waits with no time limit. It ignores a rejected Promise and starts the clock anyway. To add work to the default wait, extend the Promise in a DOMContentLoaded listener. Register the listener after the runtime’s <script> tag. The runtime sets its Promise in its own listener, which runs first. The scaffold’s deck/lesson.html waits this way for its fonts and three animation frames, so its figure has painted before t=0.
deck/lesson.html
To replace the default wait, set window.__sceneReady in a script that runs before DOMContentLoaded. A replacement removes the KaTeX wait. If the page uses data-tex, wait for window.katex yourself. Wait for a screenshot to load shows how to extend the wait for an image.

CSS hooks

The runtime adds a <style id="dt-style"> element. Its rules use only names that start with dt-. Note: A page can supply its own #dt-stage, as the scaffold’s deck/lesson.html does. The runtime adds #dt-cam after the page’s content, so the slides draw on top of it. Note: The first slide moves in 24 px from the right as it fades in over 0.3 s. The scaffold turns this off with #dt-pan > .dt-slide.dt-first { animation: none; }, so a section opens on a full frame.

Warnings

The runtime lists each warning one time in window.__decktalk.warnings. The console prints it with the prefix decktalk: . In the messages below, <id>, <step>, and <n> stand for real values. An enter function or a handler that throws goes to console.error, and the scene goes on. A render function that throws is an uncaught page error. The recorder logs it, and check reports PAGE ERROR.