05 DOCS · RECALL
Recall gives
the page back.
Every change Fizlet makes to the page goes through one ledger. It records the original and what the engine wrote. destroy() puts back everything the engine still owns, newest first, and the DOM matches the snapshot taken before. That is Recall: the reason a game can knock a page's headings around and leave nothing behind.
const e = createEngine({ root: document.body });
e.add({
render(e) {
e.ledger.style(heading, "transform", "rotate(-4deg)"); // one inline property
e.ledger.cls(heading, "smashed", true); // one class
e.ledger.attr(heading, "data-hp", "2"); // an attribute (null removes)
e.ledger.text(word, "0101"); // a text node's value
},
});
const canvas = e.ledger.add(document.createElement("canvas")); // a node you add
document.body.append(canvas);
e.start();
// Recall: the page comes back exactly; a newer edit by the page wins.
e.destroy(); // or e.ledger.restore() to keep the engineWhat it owns
ledger.text(node, value)A text node's value: the 0s and 1s a shot leaves in a word.
@fzlt/core/board-pagewrites into the page's own Text nodes this way, with no wrappers or clones.ledger.style(el, prop, value)andunstyleOne inline style property: a transform, a custom property. A style attribute comes back byte for byte.
unstyleputs one property back now and forgets it.ledger.attr(el, name, value)An attribute, set or removed (
null):aria-busy,data-hp.ledger.cls(el, name, on)One class, added or removed:
smashed,burning.ledger.add(node)A node the engine put on the page (a canvas, an overlay, debris). Recall removes it.
Three rules
- Change-only. Writing the value that is already there makes no mutation. A browser test writes the same value twice and counts zero.
- Host wins. If the host page changed something after the engine did, the ledger stops writing it and never restores over it. A write returns
falsewhen the host got there first. - Exact. After
destroy()the DOM matches a snapshot taken before the engine started, attribute for attribute and style text byte for byte. OneAbortSignalalso removes every listener and observer.
engine.ledger.restore() is Recall without destroying the engine; the Recall key on the home page demo runs exactly that. Bricks that own an element (the touch pad, the perf overlay, the match overlay) add it through the ledger, so engine.destroy() takes them too.
Questions
Why not just reload the page?
Because the page is someone else's. A reload loses their state, their scroll and their form fields. Recall undoes only what the engine did, and leaves everything else as the visitor left it.
What if my code writes the DOM directly?
Then Recall can't give it back. Write through engine.ledger (or a brick that does) in render, and the page comes back exactly.