Player
<astl-player> mounts a view, attaches the component elements, renders the chrome (pages, actions, results) and
runs one attempt. It never holds answer logic: verdicts come from a checker.
Define it once with the elements you use (astrolabe.js and astrolabe-player.js do this for the built-ins):
import { definePlayer } from '@astrolabe/player';import { builtInElements } from '@astrolabe/components/elements';
definePlayer({ elements: builtInElements }); // or only some, e.g. [gapElement]definePlayer option |
Type and meaning |
|---|---|
elements |
ElementEntry[]: component elements. A registration ({ manifest, element, messages }) is defined under its manifest tag right away; a LazyElement ({ tag, load }) is imported the first time a view contains its tag, and a load that fails shows load_failed (the next view tries again). The built-ins are lazy. |
catalogs |
MessageCatalog[]: more or overriding messages, for example another UI locale |
styleTemplates |
StyleTemplate[]: named looks that style-template picks on <astl-doc>, a component or the player: Looks |
compileSource |
SourceCompiler: turns a light-DOM source into a view and a checker (HTML with answers); astrolabe.js registers one |
urlPolicy |
UrlPolicy: which links, pictures and url attributes of a view stay; the engine's policy, or the player removes what it kept. Default isSafeUrl; one policy per page, the last call that passes one sets it. An address stays only when the policy answers true (URLs) |
registry |
CustomElementRegistry: where the elements are defined. Default: the global customElements |
Calling it again is safe: a tag already defined by the same class, or a lazy element with the same load, is skipped; a tag taken by another class, another loader or the other kind of entry throws.
What it plays
Section titled “What it plays”The player loads the first of these that it finds:
- the
viewproperty (orload({ view })); - an
<astl-doc>in its light DOM: a compiled view plays directly; a source (with author ids and answers) goes throughcompileSource, and without one the player showssource_needs_compiler; - the
srcattribute: fetched, checked againstintegrity, then played.
Attributes
Section titled “Attributes”| Attribute | Values and meaning |
|---|---|
locale |
A BCP 47 tag: the UI locale (buttons, messages, announcements). Matched against the available catalogs, with English as the fallback. Default: the player's lang, else the browser languages. |
theme |
light, dark, hc or auto: the colour theme; auto (the default) follows prefers-color-scheme. Written to the player's data-theme. |
src |
A URL: a view to fetch when no view is given. |
integrity |
A lowercase hex SHA-256: the viewHash the fetched src must match; a mismatch (or an empty value) shows integrity_mismatch. |
endpoint |
A URL: the grading endpoint of this attempt (protocol 1). Creates an httpChecker when no checker is set. |
persist |
Boolean: keep snapshots in localStorage (key astl:snapshot:<viewHash>) and restore them on load. Off by default. |
style-template |
A registered template name: the default look where neither the view's <astl-doc> nor a component names one (property styleTemplate): Looks. |
Properties
Section titled “Properties”| Property | Type and meaning |
|---|---|
view |
string: the view HTML to play. Setting it loads it. Default ''. |
policy |
AttemptPolicy: which buttons and rules apply. Default PRACTICE_POLICY. Changing it reloads the view and keeps the answers. |
checker |
Checker | null: grades checks and submits. Default null: an HTTP checker for endpoint, if set. |
snapshot |
Snapshot | null: restored on load when its viewHash matches the view (or is null). Default null. |
locale, theme, src, integrity, endpoint, persist |
The attributes above. |
state (read only) |
AttemptState: loading, ready, active, checking, submitting, submitted, review or error. |
viewHash (read only) |
string | null: SHA-256 of the mounted view; null before mounting or without WebCrypto. |
page (read only) |
number: the 0-based index of the current page. |
Methods
Section titled “Methods”| Method | Meaning |
|---|---|
load(options): Promise<void> |
Plays a view: options is { view, policy?, checker?, snapshot? }, and omitted fields keep the current properties. Resolves when it is mounted (astl-ready); rejects with the error code when it cannot. |
check(): Promise<CheckResponse | null> |
Practice: grades and shows verdicts. Failures are shown and emitted as astl-error, never thrown. |
submit(): Promise<SubmitResponse | null> |
Hands the answers in (final) and moves the focus to the result. Failures are shown and emitted, never thrown. |
goTo(index): boolean |
Goes to a page; false when not allowed (linear navigation, unknown page). |
next(): boolean, previous(): boolean |
One page forward or back. |
reset(): boolean |
Clears answers and results and goes to the first page; not after a hand-in. |
getAnswers(): Answers |
The current answers, by slot id. |
setAnswers(answers): void |
Sets answers without change events ('' clears). Only what the elements accept is kept. |
getSnapshot(): Snapshot | null |
Everything needed to restore the attempt later. |
Events
Section titled “Events”All events bubble and are composed (they cross shadow roots). Names are in PlayerEvent of @astrolabe/core.
| Event | Detail | When |
|---|---|---|
astl-ready |
ReadyDetail: { viewHash: string; pages: number; slots: number } |
the view is mounted and every element has rendered |
astl-change |
ChangeDetail: { answers: Answers } (changed slots only, '' = cleared) |
a student changed an answer (sent by the element) |
astl-page |
PageDetail: { index: number; count: number; id: string } |
the page changed |
astl-state |
StateDetail: { state: AttemptState; previous: AttemptState } |
the attempt state changed |
astl-result |
CheckResponse | SubmitResponse |
a check or a hand-in finished |
astl-snapshot |
Snapshot |
there is progress worth saving (debounced, 300 ms) |
astl-error |
ErrorDetail: { code: string; message: string } |
loading, checking or handing in failed; message is in the UI locale |
import { PlayerEvent, type Snapshot } from '@astrolabe/core';
const player = document.querySelector('astl-player')!;player.addEventListener(PlayerEvent.snapshot, (event) => { const snapshot = (event as CustomEvent<Snapshot>).detail; void fetch('/api/drafts/123', { method: 'PUT', body: JSON.stringify(snapshot) });});Error codes
Section titled “Error codes”astl-error and the player's own notices use these codes; each has a message error.<code> in the astl.player
catalog.
| Code | Meaning |
|---|---|
invalid_request, unauthorized, check_not_allowed, checks_exhausted, not_found, method_not_allowed, attempt_closed, payload_too_large, internal_error |
a problem from the checker: the grading protocol codes |
no_checker |
there is nothing to grade with (no checker, no endpoint, no compiled source) |
load_failed |
src could not be fetched, or a lazy element the view uses did not load |
view_invalid |
the view is not one <astl-doc> |
integrity_mismatch |
the fetched view does not match integrity |
source_needs_compiler |
a source with answers is in the light DOM, but no compileSource is registered (use astrolabe.js) |
source_invalid |
the source does not compile; its errors are listed under the notice for the author |
Behaviour by policy
Section titled “Behaviour by policy”| Policy | Buttons | Notes |
|---|---|---|
practice |
"Check"; "Start over" after a result | "x checks left" when maxChecks is set; "Check" is aria-disabled when no check is possible |
test |
"Hand in" | asks "Hand in anyway?" when answers are empty; shows what reveal allows |
review |
none | read only |
With navigation: 'linear' there is no "Back" button and the page progress is not clickable. With a deadline, the
header shows a countdown, the live region announces 5 and 1 minutes left, and the player hands in when it reaches
zero (the server stays authoritative).
player, header, canvas, result, footer, problem-details. See Looks.
Element contract
Section titled “Element contract”Component elements talk to the player only through PlayerElementApi (@astrolabe/core): slotIds,
getAnswers(), setAnswers(), feedback, solution, disabled, units() and attach(context); an element graded
in parts also lists its groupIds and gets their verdicts in feedback.groups. The base classes
AstlElement and SingleSlotElement in @astrolabe/player implement most of it; see
Write your own component and the API reference.