JavaScript
← All sections · part of the machine-readable /all/ index.
JavaScript
JavaScript runs in two places on Pagelove, and this section is split to match:
- Client — the
pagelove.mjs browser library: schemas, templates, two-way data binding, declarative commands, web components, and real-time mutation streaming, so you can build complete apps with minimal application JavaScript.
- Server — JavaScript that runs inside
dombase-js during composition and validation: schema bindings (default/@read/@write/@validate) and the DOM API those bindings use to traverse and build markup.
The rest of this page is the client library. For the server side, see Server-side JavaScript below.
Loading the library (client)
Most pages need only two script tags:
<script type="module" src="https://pagelove.github.io/beta-js/pagelove/sse.mjs"></script>
<script type="module" src="https://pagelove.github.io/beta-js/pagelove.mjs"></script>
Loading pagelove.mjs auto-instantiates a Pagelove instance bound to <main> when the page has one, so most pages need no application JavaScript. See The Pagelove class for auto-start details and how to construct instances explicitly.
The five files
| File |
Purpose |
pagelove.mjs |
Main entry point. Discovers schema instances and templates in HTML, renders views, binds changes bidirectionally, and routes declarative commands. |
pagelove/component.mjs |
Base class for custom elements. Provides PageloveComponent, default binders, mixin registry, and built-in Draggable/Resizable/Stackable mixins. |
pagelove/primitives.mjs |
Low-level HTTP client. PLDocument and PLElement handle range-addressed requests and selector generation. Used internally by pagelove.mjs. |
pagelove/sse.mjs |
Server-Sent Events mutation streamer. Opens an event stream on import and feeds mutations into the view. |
pagelove/debug.mjs |
Bitwise debug channels for module-level logging. Gated by a bitmask applied at import time. |
What's documented on each page
HTML patterns you write:
JavaScript API:
Real-time:
Lower layer:
- Primitives — the low-level HTTP client. Most apps don't touch it directly.
Utility:
Server-side JavaScript
The same language authors server-side schema logic, evaluated by dombase-js during composition and validation:
- JavaScript in schemas — ES modules in a property's
default, @read, @write, or @validate slot (the JavaScript peer of Sessel resolvers).
- JavaScript DOM API — the WHATWG-style DOM subset (
document, querySelector, createElement, classList, …) those bindings use to read and build markup.
Composition-time JavaScript expression bindings (j: attributes) also run server-side; they live with the other page-composition bindings under Composing pages.
See also
Schema instances in HTML
A schema instance is an HTML element marked up with Microdata that pagelove.mjs recognizes as an addressable record.
When to reach for it
Reach for an instance whenever a record needs to live on the page. Use one per note, post, comment, or any other typed item the renderer will bind to a template and the patch pipeline will mutate in place.
Anatomy of an instance
An instance is an <article> element carrying Microdata attributes. The element's tag does not have to be <article>, but create() always produces one.
| Attribute |
Required |
Purpose |
itemscope |
yes |
Marks the element as a Microdata item. |
itemtype |
yes |
Names the schema URL. Must match a registered template. |
id |
only if the instance will be edited, deleted, or bound |
Routing key for patches and view binding. |
Instances created by create() receive an auto-generated id of the form item-<base36-timestamp><random>.
How instances are discovered
On load, pagelove.mjs runs #discoverInstances() against the document. The selector is:
[itemscope][itemtype]:not(template):not([itemprop])
Discovery rules:
- Elements inside a
<template> are skipped.
- Elements carrying
itemprop are skipped — they are nested properties, not top-level instances.
- Instances whose
itemtype has no matching template in the document are skipped silently. No error is raised.
- When an explicit schema root is configured, only its direct
[itemscope][itemtype][id] children are scanned.
The renderer locates a template by exact itemtype URL match against <template itemtype="…"> elements already indexed by #discoverTemplates().
Property elements inside an instance
create() builds one child element per property, keyed off the schema type:
| Property type |
Element shape |
Text, Integer, Number, Boolean |
<meta itemprop="…" content="…"> |
Date, DateTime |
<time itemprop="…" datetime="…"> |
| Nested schema type |
A child <article itemscope itemtype="…"> |
Properties with cardinality 0..n and no value are omitted at creation and appended later. Nested schema values must be passed as an HTMLElement; raw objects are skipped.
The full grammar of property elements lives on the sibling page Schema definitions in HTML.
Examples
Primitive properties only
<article itemscope
itemtype="https://schema.host/Note"
id="item-lxk3p2m1-a7b4">
<meta itemprop="title" content="Grocery list">
<meta itemprop="body" content="Bread, olives, lemons.">
<meta itemprop="color" content="#ffd166">
</article>
Nested item
<article itemscope
itemtype="https://schema.host/Post"
id="item-lxk3p9zq-f2c8">
<meta itemprop="title" content="On discovery">
<time itemprop="publishedAt" datetime="2026-04-08T09:15:00Z"></time>
<article itemprop="author"
itemscope
itemtype="https://schema.host/Person"
id="item-lxk3pa11-91de">
<meta itemprop="name" content="Ada Park">
<meta itemprop="handle" content="ada">
</article>
</article>
The nested <article> carries both itemprop="author" (tying it to the parent) and its own itemscope/itemtype. Because it has itemprop, #discoverInstances() will not treat it as a top-level instance — it belongs to its parent.
See also
JavaScript in schemas
JavaScript in schemas lets you embed ES module source in a property's default, @read, @write, @validate, or @computed, and in a Method's implementation. The server evaluates the module on every write or read in an isolated context, sharing the request budget with Sessel. The same source is also browser-runnable, so a binding may also execute client-side under the future browser-side schema runtime.
When to reach for it
Reach for a JavaScript binding when the logic is more naturally expressed as a small ES module than a Sessel expression — for example, when reusing a familiar JavaScript idiom for string normalisation, when the same source needs to run unchanged on the server and (later) in the browser, or when the binding needs to construct schema instances via the pagelove:schema import.
JavaScript authors the default slot, the three pipeline slots (@read, @write, @validate), the schema-level @validate slot, computed properties (@computed), and method bodies (implementation). Other expression slots accept Sessel only at present: constraints, mutation handlers, HTTP queries, and e:-attribute expression bindings in SSPI templates. Group constraints and shape constraints are not expressions in either language — they are declarative Microdata and CSS selector forms.
Shape
A JavaScript binding is a typed Microdata item with itemtype="https://pagelove.org/JavaScript/Module" placed in a property's default, @read, @write, or @validate slot. Its source child carries the ES module text, conventionally inside a <script type="module"> so the same string is also browser-runnable.
<div itemprop="default" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default () => String(Math.floor(100 + Math.random() * 500));
</script>
</div>
The dispatcher selects the language by the itemtype URL of the typed item, never by <script type>. The <script> tag is a browser-execution affordance, not a server-data signal.
The export default contract
The module must have a default export, and that export must be a function — arrow or function form. The server:
- Evaluates the module in a fresh context.
- Reads the
default export off the module namespace.
- Verifies it is a function.
- Calls it with
this bound to the in-progress instance and one positional argument, context.
- Converts the return value back to a dombase value.
ES modules always run in strict mode, so arrow functions do not bind their own this. A binding that needs to read this must use a function form:
export default function() { return this.firstname; }
A module with no default export, or a default export that is not a function, fails with the shape variant.
Slot semantics
| Slot |
First argument / this |
Return value |
When it fires |
default |
this is the in-progress instance; first positional argument is context |
The default value to inject when the property is absent |
At write time, before validation |
@read |
First argument is the property value flowing through the chain |
The transformed value, passed to the next stage |
After fetch from storage, before the response is sent |
@write |
First argument is the property value flowing through the chain |
The transformed value, passed to the next stage |
Before validation, before storage |
@validate (property-level) |
First argument is the property's current value after defaults |
Truthy to accept; falsy or thrown to reject |
At persistence (PUT), after defaults, before the required-property check |
@validate (schema-level) |
this is the serialized instance (an element HTML string); the positional context argument is null for this slot |
Truthy to accept; falsy or thrown to reject |
At persistence (PUT), after cardinality, type, property-level @validate, and group constraints have all passed |
For property-level @read, @write, and @validate, the first argument is the pipeline value, not the owning instance. For default, schema-level @validate, and @computed, this is the instance — so these must use a function form to read this (an arrow function in a strict-mode ES module does not bind its own this). Method bodies also bind this to the owning instance (the Class constructor for static methods) — see Method bodies below.
Computed properties (@computed)
An @computed slot makes a property's value always derived from a binding, with no value stored for it. The binding runs on every read; assigning to the property is rejected, since there is nothing to assign to.
<div itemprop="@computed" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default function() { return this.firstName + " " + this.lastName; }
</script>
</div>
this is bound to the owning instance (a function form is required to read it). If a property declares both @computed and @read, @computed wins and @read never runs for it. A legacy, Sessel-only shorthand — an @read slot whose typed item is the bare https://pagelove.org/Sessel type — is also still recognized as a computed property for backward compatibility; new schemas should prefer @computed. See Property for the full behavior, including the legacy form.
Method bodies
A Method's implementation slot accepts a JavaScript module the same way a property binding does:
<div itemprop="property" itemscope itemtype="https://pagelove.org/Method">
<meta itemprop="name" content="greet">
<div itemprop="parameter" itemscope itemtype="https://pagelove.org/Parameter">
<meta itemprop="name" content="greeting">
</div>
<div itemprop="implementation" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default function(greeting) { return greeting + ", " + this.name + "!"; }
</script>
</div>
</div>
this is bound to the calling object — the schema instance for an instance method, or the Class constructor for a static method. Parameters are forwarded positionally, in the method's declared parameter order (Sessel implementations instead read each parameter by name). A method body may be async; the engine drives its returned Promise to settlement the same way an async default export settles.
Method bodies also dispatch when a schema method is invoked through page composition — a namespaced method element (<ns:method>) or an ns:method="…" attribute. There, this is the host element the method was dispatched on (read-only), arguments bind by name from the dispatch element's attributes (rather than positionally), an ambient read-only document is available, and the return value is spliced into the page. See Method Elements for the composition-side contract, and Methods for the schema-level declaration.
A method body dispatches in a third context too: when the method is called from another server-side expression — a trigger's action, a processor, a mutation handler, or a nested method call made by another method (whether that caller is written in Sessel or JavaScript). Here the call behaves like a direct instance.method(...) call: arguments are forwarded positionally in declared order, this is the receiver, and the return value is the method's value. A read-only document global is available only when the receiver is an element; a typed schema instance receives no document global and operates on this.
In this third context the method also has full access to the shared Context: it can read ambient entries such as Context.request, and any Context.foo = … assignment it makes is written back to the pass's Context — the same Context a Sessel method mutates in the same place — so a processor or trigger that reads Context afterwards observes the change. (Reading per-user request identity marks the response as user-specific, just as it does in composition.)
Whichever way a method is dispatched — through page composition (<ns:method> splicing its return into the page) or from another server-side expression — when it returns a typed schema instance it builds, that instance is treated exactly as new SchemaName { … }: its schema's @default values are filled in for any properties left unset, and it is validated against the schema (missing a required property with no default, or a wrong type, raises an error). So a method can construct and return an instance and rely on the same defaults and validation Sessel construction gives — you don't have to set defaulted properties yourself.
this and context for default
this — the in-progress instance
this is a read-only plain JS object view of the element being created. It exposes the schema-declared property keys that are already set — fields supplied by the client on the write, or fields set earlier in construction. Mutations to this inside a default expression are not preserved.
A default on one property may not read the value of another property whose default is also being computed in the same creation. Reading such a field returns undefined. Cross-property default ordering is not part of the public schema contract.
context — request and host information
context is a plain JS object passed as the first positional argument. The first cut carries a minimal set of well-known keys:
| Key |
Type |
Meaning |
document_html |
String |
The serialised source document being written, when one is available. |
Authors must read only the keys they need and not enumerate or rely on the exact set. Future revisions may add keys.
The document global
Separately from context, a default expression also has access to a document global — a live view of the in-progress element that supports the same DOM methods as the JavaScript DOM API, including mutations (document.querySelector(...), appending or removing elements, and so on). Any changes made through document are kept: they're applied to the element being created.
Other binding kinds that also receive a document global (for example @write bindings) get a read-only version — calling a mutating method throws.
Chaining order
When a property has pipeline bindings at multiple levels of a schema inheritance chain, stages are chained:
| Hook |
Order |
Combination rule |
@read |
Ancestor-first (root → leaf) |
The output of one stage is the input to the next. |
@write |
Child-first (leaf → root) |
The output of one stage is the input to the next. |
@validate |
Most-derived only |
The child's validator completely overrides the parent's; no chaining. |
Pipeline chains can mix Sessel and JavaScript freely across the inheritance hierarchy. A parent's Sessel stage feeds a child's JavaScript stage, and vice versa, in the order above.
Importing schemas
A schema import uses the schema URL as the module specifier, with a fixed type import attribute of "https://pagelove.org/Schema":
import Note from "https://moodboard.pagelove.org/Note" with { type: "https://pagelove.org/Schema" };
The schema URL is an identifier, not a fetchable URL. The module loader resolves the import at evaluation time by looking up the schema in the host's schema cache. An unknown schema fails with the unknown-schema variant.
Each import yields a JavaScript class with the schema's short name (the last path segment of the itemtype URL). The class is synthesised at evaluation time and supports construction, property access, instanceof, and method dispatch.
All other import specifiers (relative paths, bare specifiers, HTTP URLs) are rejected with the import-not-allowed variant. There is no pagelove:host module.
Working with imported classes
| Operation |
Behaviour |
new Foo({...}) |
Constructor accepts a plain object whose keys are schema-declared property names. Undeclared properties are stored on the instance but do not trigger pipelines. |
instance.prop |
Declared properties are readable and writable through ordinary getter/setter pairs backed by a Symbol-keyed store. |
instance instanceof Bar |
Walks the prototype chain. If Foo extends Bar, new Foo() instanceof Bar is true. |
instance.method() |
Schema-declared methods appear on the class prototype. Method bodies execute their declared implementation — Sessel or JavaScript — via the cross-language call path. |
Schemas inheriting from https://pagelove.org/Map produce classes that extend Map, with keys, values, entries, and merge exposed. Undeclared property reads fall through to the Map backing store.
Supported language features
Supported:
- ES2020+ syntax:
const/let, arrow and function forms, destructuring, spread/rest, template literals, default parameters, async/await at the expression level, optional chaining, nullish coalescing, numeric separators.
- Standard built-in globals:
Math, Date, JSON, String, Number, Array, Object, Map, Set, RegExp, Symbol, and the other ECMAScript built-ins.
- Template literals and tagged templates.
Not supported:
import statements other than pagelove:schema.
- Host I/O globals: no
fetch, no process, no require, no filesystem or environment access.
- Network and timers:
setTimeout and setInterval are not available.
Math.random() and Date.now() are permitted and return legitimately different values on the server and the browser. Bindings commit logic over inputs, not clock or RNG agreement; the server's value is what gets stored.
Resource limits
Every evaluation runs under a per-request budget. In production the budget is read from the host's https://pagelove.org/TransactionBudget Microdata, shared with Sessel. A request touching one Sessel binding and one JavaScript binding sees a single shared budget, not two competing ones.
| Limit |
Source in production |
Default in unbudgeted contexts |
Exhaustion error |
| Memory |
Remaining memory budget on the request |
16 MB per context |
out-of-memory |
| Stack |
Per-thread default |
256 KB per context |
threw (typically InternalError: stack overflow) |
| Time |
Remaining time budget on the request |
Per-thread default |
timeout |
| Ops |
Charged in batches against the request budget on every periodic interrupt |
Not charged for short, straight-line code |
Surfaces via the request budget |
Errors
Every failure is rendered to the client as an HTML Microdata document of type https://pagelove.org/BindingFailure, nested inside the https://pagelove.org/SchemaViolation envelope.
| Variant |
Trigger |
parse |
The module source fails to parse as an ES module. |
shape |
The module parsed but has no default export, or the default export is not a function. |
threw |
The default function ran and threw. The message and (when available) stack are carried in the failure item. |
timeout |
The evaluation exceeded the time budget. |
out-of-memory |
The evaluation exceeded the memory budget. |
marshal |
An input value (a field of this, or a key of context) cannot be converted to a JavaScript value. |
return-type |
The return value cannot be converted back into a dombase value. Functions, symbols, cyclic objects, and objects nested deeper than 64 levels all fall here. |
import-not-allowed |
The module source contains an import specifier other than pagelove:schema. |
unknown-schema |
A pagelove:schema import referenced a schema itemtype URL not found in the host's schema cache. |
unknown-language |
The slot carried a typed item whose itemtype URL matches no registered language. |
The rendered failure carries at minimum:
<div itemscope itemtype="https://pagelove.org/BindingFailure">
<meta itemprop="language" content="https://pagelove.org/JavaScript/Module">
<meta itemprop="variant" content="threw">
<p itemprop="message">TypeError: Cannot read properties of undefined (reading 'foo')</p>
<pre itemprop="stack"> at default (eval:2:17)</pre>
</div>
The stack property is present for threw when the engine provided one and absent otherwise. Sessel bindings produce structurally identical BindingFailure items with a different language value.
Tracing
Every JavaScript evaluation produces an OpenTelemetry-compatible span named dombase_js.evaluate:
| Attribute |
Source |
schema.itemtype |
The schema this binding belongs to, or "(none)". |
binding.kind |
"default", "read", "write", "validate", "computed", "schema-@validate", or "method". (Other binding contexts — triggers, processors, WebDAV auth — use their own kind values; not covered here.) |
binding.source_hash |
Short hex-encoded fingerprint of the source. |
binding.source_len |
Length of the source string in bytes. |
outcome |
"ok" on success, or the failure variant name. |
budget.memory_delta_bytes |
Bytes allocated during evaluation. |
budget.time_nanos |
Wall-clock nanoseconds for the evaluation. |
A child span dombase_js.compile wraps the compile step on the first use of a given source on a thread. Cross-language Sessel calls from within JavaScript nest as children of the dombase_js.evaluate span.
Marshalling
Values flow between dombase and JavaScript at every binding boundary:
| Direction |
Behaviour |
dombase → JS (inputs to this, context, pipeline argument) |
Each value is converted to its JavaScript equivalent. Values that cannot be converted fail the binding with marshal. |
| JS → dombase (return value) |
The value is converted back to a dombase value. Functions, symbols, cyclic objects, and objects nested deeper than 64 levels fail with return-type. |
Date round-trips |
A dombase temporal value passed into this/context, or a JS Date returned from a binding, currently unmarshalls as a plain Map of the Date object's own properties rather than as a dombase temporal value. Bindings that need a temporal default should return an ISO-8601 string. |
this traversal |
this is a placeholder object seeded only with the explicitly set schema-declared fields the marshaller currently understands. Rich traversal of the in-progress element's DOM subtree is not yet wired through. |
First-cut exclusions
The following are out of scope for the current cut. Each is either a deferred feature or an interim limitation that will be lifted without breaking existing bindings:
- Imports other than
pagelove:schema. No pagelove:host module. No relative or HTTP imports.
- Constraints, mutation handlers, HTTP queries, and
e:-attribute expression bindings in SSPI templates. All Sessel-only at present.
- Cross-property
this access on default. A default cannot read another property whose default is also being computed on the same creation.
- Browser-side execution of these bindings. The source-level contract that makes browser-side execution possible is committed; the runtime that calls it client-side is a future spec.
Examples
Random coordinate default
<div itemprop="default" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default () => String(Math.floor(100 + Math.random() * 500));
</script>
</div>
Timestamp default reading context
<div itemprop="default" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default function(context) {
return `created at ${new Date().toISOString()}`;
}
</script>
</div>
Normalise on write
<div itemprop="@write" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default (val) => typeof val === 'string' ? val.trim().toLowerCase() : val;
</script>
</div>
<div itemprop="@read" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default (val) => typeof val === 'string' ? val.toUpperCase() : val;
</script>
</div>
Validate at persistence
<div itemprop="@validate" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default (val) => typeof val === 'string' && val.includes('@');
</script>
</div>
Default that constructs a schema instance
<div itemprop="default" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
import Note from "https://moodboard.pagelove.org/Note" with { type: "https://pagelove.org/Schema" };
export default () => new Note({ title: "untitled", x: 0, y: 0 });
</script>
</div>
Computed property combining two fields
<div itemprop="@computed" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default function() { return this.firstName + " " + this.lastName; }
</script>
</div>
Method body using a parameter and this
<div itemprop="implementation" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default function(greeting) { return greeting + ", " + this.name + "!"; }
</script>
</div>
See also
- JavaScript DOM API — the DOM subset (
document, querySelector, createElement, classList, …) a JavaScript binding can use to traverse and build markup
- Property — the slot in which
default, @read, @write, @validate, and @computed are declared
- Methods — the schema-level declaration a method body's
implementation slot belongs to
- Method Elements — invoking a method during page composition
- Resolvers —
@read and @write pipeline semantics shared with Sessel
- Schema — inheritance, which determines pipeline chain order
- Sessel — the peer binding language; both share the same slots and error envelope
- Schema definitions in HTML — the client-side counterpart that runs JavaScript modules in the browser
HTMLAnchorElement
The interface for <a>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
href |
href |
string |
Reflects verbatim — no base-URL resolution. |
target |
target |
string |
Reflects the content attribute verbatim. |
rel |
rel |
string |
Reflects the content attribute verbatim. |
download |
download |
string |
Reflects the content attribute verbatim. |
hreflang |
hreflang |
string |
Reflects the content attribute verbatim. |
type |
type |
string |
Reflects the content attribute verbatim. |
referrerPolicy |
referrerpolicy |
enum |
Keywords: "" · no-referrer · no-referrer-when-downgrade · same-origin · origin · strict-origin · origin-when-cross-origin · strict-origin-when-cross-origin · unsafe-url. Missing → ""; invalid → "". |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
JavaScript DOM API
JavaScript bindings — schema methods and the @read / @write / @validate / @computed resolvers declared as JavaScript modules — can traverse and build markup with a WHATWG-style DOM API. It is exposed through the ambient document global and through node/element handles.
This is a subset chosen to make isomorphic (server and browser) bindings writable; anything not listed in these pages is not available server-side. Each interface is documented on its own page:
- Document — the
document global: querying, node factories, and documentElement/head/body.
- Element — attributes, content (
innerHTML/outerHTML/textContent), classList, element traversal, and insertion.
- Node — traversal and tree mutation shared by every node, plus the
Node type constants.
- NodeList — the static collection returned by queries and child lists.
- DOMParser and XMLSerializer — parse a fresh document, serialise a node to a string.
- DOMException — the error type every thrown DOM error is an instance of, and its legacy
name → code table.
Interfaces and instanceof
The WHATWG node interfaces exist as real classes, with working instanceof and constructor.name, in the standard hierarchy:
Node → Document, DocumentFragment, Element → HTMLElement → per-tag interfaces (HTMLAnchorElement, HTMLInputElement, …; and HTMLMediaElement → HTMLVideoElement/HTMLAudioElement), CharacterData
CharacterData → Text, Comment
So p instanceof Element, p instanceof Node, and textNode instanceof CharacterData all hold — a binding can branch on node kind the same way it would in the browser. HTML elements (HTML-parsed or createElement) are HTMLElement (so htmlEl instanceof HTMLElement, and htmlEl.constructor.name is "HTMLElement"); elements in another namespace (createElementNS, e.g. SVG) are plain Element. Members are interface-scoped: reaching for a member that is not part of a node's interface yields undefined (for example textNode.tagName and element.data are both undefined) rather than throwing. Within a node's own interface, an accessor with no value returns null (for example element.parentNode on a detached element).
Per-tag element interfaces. Every non-deprecated HTML tag that has its own dedicated interface in the WHATWG spec has one here too, below HTMLElement — an <a> is an HTMLAnchorElement, an <input> an HTMLInputElement, and so on (a instanceof HTMLAnchorElement, a.constructor.name === "HTMLAnchorElement"; and the whole chain up to Node holds). Each has its own reference page listing its reflected IDL attributes (a.href, img.src, input.required, …) — see the Element interfaces index for the full list of interfaces and their pages. A handful of obsolete WHATWG §16.3 elements (<font>, <marquee>, …) also have their interface, marked deprecated on their page. An HTML tag with no dedicated interface — either because the spec never gave it one (<section>, <article>, …) or it isn't yet covered — is a plain HTMLElement with no reflected properties beyond HTMLElement's own (so section.href is undefined); use getAttribute / setAttribute there. A single flattened node still backs every node internally — the interfaces are a prototype layer over it.
Availability and the read-only boundary
The ambient document global is present whenever the binding runs against a document. Whether it is writable depends on the binding slot:
| Binding slot |
Ambient document |
A default resolver (the value materialised for a new instance) |
Writable |
@read, @write, @validate, @computed; schema methods; trigger when/action |
Read-only tree, writable construction |
A document you create yourself with new DOMParser().parseFromString(…) |
Writable |
A read-only ambient document protects the existing tree: mutating a node that is already in the document — setting an attribute, changing text, inserting or removing a child — throws a NoModificationAllowedError (message: "document is read-only in this binding context"). Read-only membership is a property of the tree as it stood when the binding started, not of how you reached a node: every node that was in the document is read-only through any path (document.body, querySelector, parentNode, a NodeList, classList), so a node cannot be laundered into a writable handle by reaching it a different way.
Constructing new nodes is always allowed, even against a read-only document. createElement, createElementNS, createTextNode, createComment, createDocumentFragment, and cloneNode return fresh, writable detached nodes; building a subtree from them and returning it works with the standard DOM API:
export default (title) => {
const li = document.createElement("li");
li.textContent = title;
return li; // return an element — see "Returning DOM"
};
The one thing you cannot do is move a node out of the read-only tree into your constructed subtree — that would mutate the tree it belongs to, so card.appendChild(document.querySelector("li")) throws NoModificationAllowedError. To reuse existing content, copy it with cloneNode(true), which yields a writable copy you can attach freely:
const copy = document.querySelector("li").cloneNode(true);
card.appendChild(copy); // fine — a clone is a fresh, writable node
Mutations to a writable ambient document (a default resolver, or a document you parsed yourself) are serialised back and persisted after the binding returns.
Returning DOM from a binding
The value a binding returns is spliced into the composed document:
| Returned value |
Result |
| An element node |
Serialised and spliced in place. |
A NodeList or array of elements |
Each element serialised and spliced, in order. |
| A non-element node (text, comment, document, fragment) |
An error — the message tells you the fix, e.g. return document.documentElement instead of the document, or use .textContent instead of a text node. |
Errors
Thrown errors are DOMException instances with the standard name/code/message. new DOMException(message?, name?) is available, and the full legacy name → code table is supported — see the DOMException reference. The names actually raised by this API:
| Name |
Raised when |
SyntaxError |
Invalid CSS selector; invalid insertAdjacentHTML position. |
HierarchyRequestError |
A tree mutation would create a cycle. |
NotFoundError |
removeChild / insertBefore / replaceChild reference is not a child. |
NamespaceError |
Malformed qualified name in createElementNS / setAttributeNS. |
NoModificationAllowedError |
Mutating a node already in a read-only tree, or moving such a node into a constructed subtree (copy it with cloneNode(true) instead); outerHTML set on a parentless element. |
Divergences from the browser DOM
- Per-tag element interfaces carry reflected IDL attributes (each interface's own page lists them); a tag with no dedicated interface is a plain
HTMLElement with no reflected properties beyond HTMLElement's own (use getAttribute / setAttribute). Where reflection is present, two divergences are inherent to a static server DOM: value-like properties (input.value, option.value, textarea.value) reflect the content attribute (the browser's defaultValue), not live editing state; and URL properties (.href, .src) reflect verbatim with no base-URL resolution. See Reflected properties: shared semantics for the numeric/enum/contentEditable canonicalization rules.
querySelector / querySelectorAll called on an element scan the whole document, not the element's subtree (unlike the browser). getElementsByTagNameNS, closest, matches, getElementById, and children are receiver/subtree-scoped.
children (and all query results) are a static NodeList, not a live HTMLCollection.
tagName case is keyed on the stored namespace: uppercased for elements with no namespace (HTML-parsed elements and createElement), verbatim for createElementNS.
setAttributeNS stores the qualified name verbatim with no per-attribute namespace map; retrievability via getAttributeNS depends on an in-scope xmlns: prefix mapping the URI.
createElementNS does not auto-emit xmlns: declarations, and its NamespaceError validation omits the browser's reserved xml / xmlns prefix rules.
- CSS namespace-pipe selectors (
p|tag, *|tag) are unsupported (p| throws SyntaxError; *| matches nothing).
DOMParser().parseFromString ignores the MIME type (always text/html).
- DOM operations are charged against the request's composition budget.
See also
- JavaScript bindings — declaring
@read/@write/@validate/@computed/default resolvers and methods as JavaScript modules
- Methods — schema methods (which can build and return DOM)
- Method Elements — invoking a method from a page; how a returned element is spliced
Document
Members of the Document interface, reached through the ambient document global: querying the tree, creating nodes, and reaching the document's structural elements. The factories are mutation-guarded and throw NoModificationAllowedError on a read-only document.
Querying
querySelector
querySelector(selector) → the first matching element, or null. An invalid selector throws SyntaxError.
Divergence: it scans the whole document even when called on an element (not the receiver's subtree).
const title = document.querySelector("main h1");
querySelectorAll
querySelectorAll(selector) → a static NodeList of every match. Invalid selector throws SyntaxError. Also a whole-document scan.
for (const li of document.querySelectorAll("ul#todo > li")) {
li.classList.add("seen");
}
getElementById
getElementById(id) → the element with that id, or null. The match is a literal string comparison on the id attribute — no CSS parsing, so ., :, and [ match literally. Scoped to the receiver's subtree (a divergence from the browser, where it is always document-wide).
const cart = document.getElementById("cart");
getElementsByTagNameNS
getElementsByTagNameNS(namespace, localName) → a NodeList, scoped to the receiver's descendants (excluding the receiver). "*" matches any namespace or any local name.
const cells = row.getElementsByTagNameNS("*", "td");
Creating nodes
Factory methods returning detached nodes. All are mutation-guarded.
createElement
createElement(tag) → a detached element. tagName later reports the tag uppercased (no namespace).
const li = document.createElement("li");
li.textContent = "New item";
createElementNS
createElementNS(namespace, qualifiedName) → a detached namespaced element. qualifiedName is stored verbatim (case preserved); namespace is recorded as the element's namespace URI. Throws NamespaceError for a malformed qualified name (empty, more than one :, a leading/trailing :, or a prefix with an empty namespace). No xmlns: declaration is auto-emitted.
const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
createTextNode
createTextNode(data) → a detached text node.
const t = document.createTextNode("Hello");
createComment(data) → a detached comment node.
const c = document.createComment("build: 2026-07-02");
createDocumentFragment
createDocumentFragment() → a detached fragment. Appending the fragment moves its children into the target (leaving the fragment empty).
const frag = document.createDocumentFragment();
for (const name of names) {
const li = document.createElement("li");
li.textContent = name;
frag.appendChild(li);
}
list.appendChild(frag); // moves every <li> in at once
Document structure
Accessors that reach the document's structural elements — each returns the element or null.
documentElement
The root element (<html>).
const lang = document.documentElement.getAttribute("lang");
head / body
The <head> and <body> elements.
document.body.classList.add("ready");
See also
Schema definitions in HTML
Schema definitions in HTML
A schema definition is an HTML element marked up with Microdata that pagelove.mjs reads on load to learn the shape of a record type.
When to reach for it
Reach for a schema definition whenever a new kind of record needs to exist on the page — a Note, a Post, a Comment — and pagelove.mjs must know how to create, render, and bind instances of it client-side.
Anatomy of a schema definition
A schema definition is a <div> (or any element) carrying itemscope and itemtype="https://pagelove.org/Schema". #discoverSchemas() walks every such element on the page.
| Child |
Required |
Purpose |
<meta itemprop="type" content="…"> |
yes |
The URL that names this schema. Instances reference it via itemtype. |
<meta itemprop="parent" content="…"> |
no |
URL of another schema to inherit properties from. |
[itemprop="property"] children |
one or more |
Each declares a single property. See below. |
A schema with no type child is skipped silently.
Property definitions
Each property is an inner itemscope of type https://pagelove.org/Property. A <li> is conventional, but any element works. Its children declare the four fields:
| Field |
Required |
Accepts |
<meta itemprop="name" content="…"> |
yes |
The property name. Properties without a name are dropped. |
<meta itemprop="type" content="…"> |
optional |
A type URL such as https://pagelove.org/Text, Integer, DateTime, or a nested schema URL. Defaults to the empty string if absent. |
<meta itemprop="cardinality" content="…"> |
optional |
0..1, 1..1, 0..n, 1..n. Defaults to 0..1 if absent. |
itemprop="default" child |
optional |
Either a <meta> with a content string, or an embedded client-side JavaScript/Module (see below). |
An additional itemprop="@read" child may carry an embedded client-side JavaScript/Module that transforms the value on read.
Inheritance
A schema may declare <meta itemprop="parent" content="…"> pointing at another schema's type URL. #discoverSchemas() resolves inheritance in a second pass:
- Parent properties are inherited first.
- The child's own properties override any parent property with the same
name. Child wins.
- An unknown parent URL throws
Schema "<child>" declares unknown parent "<parent>".
- An inheritance cycle throws
Schema inheritance cycle detected at "<url>".
Only direct property-name collisions override; unrelated parent properties remain.
Static defaults
Place <meta itemprop="default" content="…"> directly inside a property's itemscope. The value is always a string and is used as-is when a new instance is created.
Client-side dynamic defaults
For defaults that must be computed, embed a JavaScript/Module inside the property:
<li itemprop="property" itemscope itemtype="https://pagelove.org/Property">
<meta itemprop="name" content="createdAt">
<meta itemprop="type" content="https://pagelove.org/DateTime">
<div itemprop="default" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default () => new Date().toISOString();
</script>
</div>
</li>
When pagelove.mjs loads the schema on a page, its loadModule helper finds the wrapper, reads the child <script itemprop="source">, wraps the script text in a Blob, creates a Blob URL with URL.createObjectURL, imports that URL as an ES module, and assigns the module's default export as the property's default. This happens in the browser, on page load, not on the server. The module is invoked whenever pagelove.mjs needs a default value client-side — typically when a new instance is about to be created before the POST.
Same embedding pattern, but the wrapper's itemprop is @read instead of default:
<div itemprop="@read" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default (value) => value.toUpperCase();
</script>
</div>
pagelove.mjs loads this module the same way — Blob URL, dynamic import, default export — and calls it to transform the property value when a client-side consumer reads the property. Like dynamic defaults, @read runs in the browser.
Examples
A schema with static defaults
<div itemscope itemtype="https://pagelove.org/Schema">
<meta itemprop="type" content="https://schema.host/Note">
<ul>
<li itemprop="property" itemscope itemtype="https://pagelove.org/Property">
<meta itemprop="name" content="title">
<meta itemprop="type" content="https://pagelove.org/Text">
<meta itemprop="cardinality" content="1..1">
<meta itemprop="default" content="Untitled">
</li>
<li itemprop="property" itemscope itemtype="https://pagelove.org/Property">
<meta itemprop="name" content="body">
<meta itemprop="type" content="https://pagelove.org/Text">
</li>
<li itemprop="property" itemscope itemtype="https://pagelove.org/Property">
<meta itemprop="name" content="color">
<meta itemprop="type" content="https://pagelove.org/Text">
<meta itemprop="default" content="#ffd166">
</li>
</ul>
</div>
A schema that inherits from a parent
<div itemscope itemtype="https://pagelove.org/Schema">
<meta itemprop="type" content="https://schema.host/Content">
<ul>
<li itemprop="property" itemscope itemtype="https://pagelove.org/Property">
<meta itemprop="name" content="title">
<meta itemprop="type" content="https://pagelove.org/Text">
<meta itemprop="cardinality" content="1..1">
</li>
<li itemprop="property" itemscope itemtype="https://pagelove.org/Property">
<meta itemprop="name" content="body">
<meta itemprop="type" content="https://pagelove.org/Text">
</li>
</ul>
</div>
<div itemscope itemtype="https://pagelove.org/Schema">
<meta itemprop="type" content="https://schema.host/Post">
<meta itemprop="parent" content="https://schema.host/Content">
<ul>
<li itemprop="property" itemscope itemtype="https://pagelove.org/Property">
<meta itemprop="name" content="publishedAt">
<meta itemprop="type" content="https://pagelove.org/DateTime">
</li>
</ul>
</div>
Post inherits title and body from Content and adds publishedAt. A title property declared on Post would override the parent's.
A schema with a client-side dynamic default
<div itemscope itemtype="https://pagelove.org/Schema">
<meta itemprop="type" content="https://schema.host/Event">
<ul>
<li itemprop="property" itemscope itemtype="https://pagelove.org/Property">
<meta itemprop="name" content="label">
<meta itemprop="type" content="https://pagelove.org/Text">
</li>
<li itemprop="property" itemscope itemtype="https://pagelove.org/Property">
<meta itemprop="name" content="createdAt">
<meta itemprop="type" content="https://pagelove.org/DateTime">
<div itemprop="default" itemscope itemtype="https://pagelove.org/JavaScript/Module">
<script itemprop="source" type="module">
export default () => new Date().toISOString();
</script>
</div>
</li>
</ul>
</div>
When pagelove.mjs builds a new Event in the browser, it calls the module's default export and stamps createdAt with the current time in the user's browser before the instance is posted.
Not supported client-side
pagelove.mjs's schema discovery only reads name, type, cardinality, a static or dynamic default, and a @read transform from each property — it does not implement computed properties (@computed), methods (itemtype="https://pagelove.org/Method"), or schema-level @validate. Declaring any of these in a schema the client library discovers is inert: the extra markup is silently ignored.
All three are real, server-side features — see JavaScript in schemas for computed properties, methods, and schema-level @validate as core evaluates them.
See also
HTMLAreaElement
The interface for <area>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
alt |
alt |
string |
Reflects the content attribute verbatim. |
href |
href |
string |
Reflects verbatim — no base-URL resolution. |
target |
target |
string |
Reflects the content attribute verbatim. |
download |
download |
string |
Reflects the content attribute verbatim. |
rel |
rel |
string |
Reflects the content attribute verbatim. |
hreflang |
hreflang |
string |
Reflects the content attribute verbatim. |
type |
type |
string |
Reflects the content attribute verbatim. |
shape |
shape |
string |
Reflects the content attribute verbatim. |
coords |
coords |
string |
Reflects the content attribute verbatim. |
referrerPolicy |
referrerpolicy |
enum |
Keywords: "" · no-referrer · no-referrer-when-downgrade · same-origin · origin · strict-origin · origin-when-cross-origin · strict-origin-when-cross-origin · unsafe-url. Missing → ""; invalid → "". |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTML bindings
An HTML binding is a data-bind* attribute on a view element that pagelove.mjs uses to populate that element from a schema instance — and, when the element is editable, to write user edits back into the schema.
When to reach for it
Reach for a binding whenever a view element needs to show a value from a schema article, or whenever a user edit on the view needs to flow back into the record. Bindings are how the rendered light-DOM view of an instance stays in sync with the underlying <article> without any imperative wiring.
The three binding attributes
| Attribute |
Direction |
What it does |
data-bind="prop" |
two-way (when the element is editable) |
The element's text content (or value, on form controls) reflects the named property. User edits are written back to the schema article. |
data-bind-attr="prop1 prop2" |
read-only |
Forwards each named property to a data-* attribute on the view root itself. color becomes data-color, x becomes data-x. Useful for CSS hooks. |
data-bind-<htmlattr>="prop" |
read-only |
Binds one specific HTML attribute to a property value. data-bind-href="url" sets href, data-bind-src="photo" sets src, data-bind-datetime="publishedAt" sets datetime. |
Property lookup is always scoped: pagelove.mjs resolves each prop against the direct [itemprop="<prop>"] children of the current schema scope, not against descendants.
Two-way updates
A data-bind element participates in writeback when user input reaches it through one of the delegated DOM events handled by pagelove.mjs:
| Event |
Target selector |
Purpose |
change |
any [data-bind] |
Commit on form-control change (checkbox, select, native date picker). |
focusout |
[contenteditable][data-bind], input[data-bind], select[data-bind], textarea[data-bind] |
Commit when the element loses focus after editing. |
input |
the same editable selectors |
Live commits, debounced so each keystroke does not hit the schema. |
[contenteditable] elements participate automatically because they fire focusout and input the same way <input> and <textarea> do. No extra markup is required to make a contenteditable heading writeable — the data-bind attribute is enough.
Form controls (input, select, textarea) read and write through the element's value. Every other element reads and writes through textContent. Writes are idempotent: the binder compares before writing, so an unchanged value produces no DOM mutation.
Repetition
A single data-bind element can stamp multiple view elements when the matching schema property repeats. Two conditions trigger repetition:
- The view element carries
itemscope — it is treated as a stamp for a nested schema type and is always repeated, even if the current property value list is empty.
- The schema scope contains more than one direct child matching
[itemprop="<prop>"] — the stamp is repeated once per value.
#repeatElement() performs the stamp. The original element is removed from the DOM and replaced with a comment marker of the form <!--data-bind:<prop>-->. For each matching schema child, a clone of the stamp is inserted after the marker. If the schema child has no itemscope, the clone receives the scalar value written into its text content. If the schema child is itself an itemscope, the clone is linked to it via data-for="<schemaId>" and #populateBindings() recurses into the clone against the nested schema scope.
Nested scopes
A data-bind that sits inside a deeper [data-for] element is owned by that inner scope, not by the outer pass. During the outer viewRoot.querySelectorAll('[data-bind]') iteration, any element whose closest [data-for] ancestor is not the current viewRoot is skipped. The same rule applies to the data-bind-<htmlattr> sweep. This is what allows nested components to manage their own bindings without the parent rewriting them on every pass.
Examples
Two-way text binding on a heading
<template itemtype="https://schema.host/Note">
<article class="note">
<h1 data-bind="title" contenteditable></h1>
<p data-bind="body" contenteditable></p>
</article>
</template>
The heading and paragraph reflect the instance's title and body. Editing either in place commits back to the schema article on focusout and during input (debounced).
Forwarding properties as data-* attributes
<template itemtype="https://schema.host/StickyNote">
<article class="sticky" data-bind-attr="color x y">
<h1 data-bind="title" contenteditable></h1>
</article>
</template>
The root <article> receives data-color, data-x, and data-y reflecting the matching properties on the instance. CSS can then read them:
.sticky { background: attr(data-color); transform: translate(attr(data-x px), attr(data-y px)); }
Binding an HTML attribute
<template itemtype="https://schema.host/Link">
<article>
<a data-bind-href="url" data-bind="label"></a>
<time data-bind-datetime="publishedAt" data-bind="publishedAt"></time>
</article>
</template>
The <a> gets its href from url and its visible text from label. The <time> gets its datetime attribute from publishedAt and its visible text from the same property.
See also
HTMLAudioElement
The interface for <audio>. Extends HTMLMediaElement → HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLMediaElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
Element
The element surface: identity, attributes, content, classList, element-only traversal, and insertion. All setters and mutators are guarded and throw NoModificationAllowedError on a read-only document. Tree mutation shared with every node (appendChild, remove, …) lives on the Node page.
Identity
Read-only accessors describing the element:
| Accessor |
Value |
tagName |
Tag name — uppercased for no-namespace elements (HTML-parsed and createElement), verbatim for createElementNS. |
localName |
The part after the first :. |
prefix |
The namespace prefix, or null. |
namespaceURI |
The resolved namespace URI (stored, or walked from an ancestor xmlns:*), or null. |
id |
The id attribute, or "". |
className |
The whole class attribute, or "". |
const el = document.querySelector("svg > g");
el.tagName; // "G" (or verbatim if created with createElementNS)
el.id; // "" when absent
Attributes
A set of high-frequency elements expose reflected IDL properties that read and write the matching content attribute — a.href, img.src/img.alt, input.type/input.value/input.required, and other form-control properties (see Reflected IDL attributes below and per-tag interfaces). Elements outside that set are a plain HTMLElement with no reflected properties. Either way, the getAttribute / setAttribute methods below work on every element and are the general mechanism.
getAttribute
getAttribute(name) → the value, or null when absent.
const href = link.getAttribute("href");
hasAttribute
hasAttribute(name) → boolean.
if (input.hasAttribute("required")) { /* … */ }
setAttribute
setAttribute(name, value) — sets or replaces the attribute. Guarded.
link.setAttribute("rel", "noopener");
removeAttribute
removeAttribute(name) — removes it; a no-op when absent. Guarded.
input.removeAttribute("disabled");
getAttributeNS / setAttributeNS / removeAttributeNS
The namespaced variants. getAttributeNS(ns, localName) resolves the URI to an in-scope xmlns: prefix, then reads prefix:localName (null if no in-scope prefix maps the URI). setAttributeNS(ns, qualifiedName, value) stores the attribute under qualifiedName verbatim — the ns argument is used only to validate the qualified name (throws NamespaceError if malformed). removeAttributeNS(ns, localName) resolves URI → prefix and removes prefix:localName.
el.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "#icon");
el.getAttributeNS("http://www.w3.org/1999/xlink", "href"); // "#icon"
Reflected IDL attributes
For a set of high-frequency element interfaces, common IDL properties are reflected: reading the property returns the content attribute (or "" when absent, false for boolean properties), and writing it sets — or, for a falsy boolean, removes — the attribute. They are exactly equivalent to getAttribute/setAttribute on the underlying attribute; use whichever reads better.
const a = document.querySelector("a");
a.href; // reads the href attribute ("" if absent)
a.href = "/next"; // sets it — a.getAttribute("href") === "/next"
const input = document.querySelector("input");
input.required = true; // adds the boolean attribute
input.required; // → true (input.hasAttribute("required"))
Every interface has its own reference page, listing its reflected properties (see Reflected properties: shared semantics below for how numeric/enum/boolean reflection works in general):
| Interface |
Tag(s) |
HTMLElement |
(any tag with no more specific interface below) |
HTMLAnchorElement |
<a> |
HTMLAreaElement |
<area> |
HTMLAudioElement |
<audio> |
HTMLBRElement |
<br> |
HTMLBaseElement |
<base> |
HTMLBodyElement |
<body> |
HTMLButtonElement |
<button> |
HTMLCanvasElement |
<canvas> |
HTMLDListElement |
<dl> |
HTMLDataElement |
<data> |
HTMLDataListElement |
<datalist> |
HTMLDetailsElement |
<details> |
HTMLDialogElement |
<dialog> |
HTMLDirectoryElement † |
<dir> |
HTMLDivElement |
<div> |
HTMLEmbedElement |
<embed> |
HTMLFieldSetElement |
<fieldset> |
HTMLFontElement † |
<font> |
HTMLFormElement |
<form> |
HTMLFrameElement † |
<frame> |
HTMLFrameSetElement † |
<frameset> |
HTMLHRElement |
<hr> |
HTMLHeadElement |
<head> |
HTMLHeadingElement |
<h1>, <h2>, <h3>, <h4>, <h5>, <h6> |
HTMLHtmlElement |
<html> |
HTMLIFrameElement |
<iframe> |
HTMLImageElement |
<img> |
HTMLInputElement |
<input> |
HTMLLIElement |
<li> |
HTMLLabelElement |
<label> |
HTMLLegendElement |
<legend> |
HTMLLinkElement |
<link> |
HTMLMapElement |
<map> |
HTMLMarqueeElement † |
<marquee> |
HTMLMediaElement |
(abstract — no tag) |
HTMLMenuElement |
<menu> |
HTMLMetaElement |
<meta> |
HTMLMeterElement |
<meter> |
HTMLModElement |
<ins>, <del> |
HTMLOListElement |
<ol> |
HTMLObjectElement |
<object> |
HTMLOptGroupElement |
<optgroup> |
HTMLOptionElement |
<option> |
HTMLOutputElement |
<output> |
HTMLParagraphElement |
<p> |
HTMLParamElement † |
<param> |
HTMLPictureElement |
<picture> |
HTMLPreElement |
<pre> |
HTMLProgressElement |
<progress> |
HTMLQuoteElement |
<blockquote>, <q> |
HTMLScriptElement |
<script> |
HTMLSelectElement |
<select> |
HTMLSlotElement |
<slot> |
HTMLSourceElement |
<source> |
HTMLSpanElement |
<span> |
HTMLStyleElement |
<style> |
HTMLTableCaptionElement |
<caption> |
HTMLTableCellElement |
<td>, <th> |
HTMLTableColElement |
<col>, <colgroup> |
HTMLTableElement |
<table> |
HTMLTableRowElement |
<tr> |
HTMLTableSectionElement |
<thead>, <tbody>, <tfoot> |
HTMLTemplateElement |
<template> |
HTMLTextAreaElement |
<textarea> |
HTMLTimeElement |
<time> |
HTMLTitleElement |
<title> |
HTMLTrackElement |
<track> |
HTMLUListElement |
<ul> |
HTMLVideoElement |
<video> |
† = a deprecated element (WHATWG HTML §16.3 "Other elements, attributes and APIs"); its interface exists only for instanceof / constructor.name and content-attribute reflection fidelity — the tag is obsolete and should not be used in new content. Some interfaces cover more than one tag (blockquote/q, ins/del, the table sections/cells/cols, the six headings h1–h6). video and audio are HTMLMediaElement subclasses: video instanceof HTMLVideoElement and video instanceof HTMLMediaElement both hold, and both inherit the shared HTMLMediaElement properties (so video.autoplay and audio.controls work), while video-only properties like poster are undefined on an audio.
Reflected properties: shared semantics
Numeric IDL attributes (e.g. td.colSpan/rowSpan, ol.start, img/canvas/video width/height, progress.value/max, meter.*) reflect as the browser's coerced number with per-attribute defaults and clamping — e.g. unset td.colSpan is 1. Enumerated IDL attributes (e.g. input.type, form.method, img/iframe loading, referrerPolicy, and the global dir/inputMode/enterKeyHint/autocapitalize on HTMLElement) canonicalize to their keyword with WHATWG missing/invalid defaults — e.g. unset input.type is "text". One enumerated attribute takes a non-standard shape: crossOrigin is a nullable enum — a missing attribute reflects as null, any present value other than "use-credentials" maps to "anonymous", and assigning null removes the attribute. A few attributes reflect as a string even though the WHATWG IDL might suggest otherwise: embed/object width/height, ol.type, area.shape/coords (verbatim, uncanonicalized, case preserved), and the deprecated §16.3 interfaces' numeric-looking attributes (marquee.*). contentEditable (on HTMLElement) is reflected through a bespoke accessor, not the enum path — see its page for the getter/setter shape.
A property is only present on its own interface — img.href is undefined, not an error (see interface scoping). Two intentional divergences: value-like properties (input.value, option.value, textarea.value) reflect the content attribute (the browser's defaultValue), not live editing state, because the server DOM is static; and URL properties (.href, .src) reflect verbatim with no base-URL resolution.
Content
textContent is documented with the Node content members. The HTML-string members below are element-only.
innerHTML
Get returns the serialised child content. Set parses only the assigned string — the document is never re-serialised and re-parsed. Guarded.
section.innerHTML = "<p>Loaded.</p>";
outerHTML
Get returns the element and its children serialised. Set replaces the element within its parent; throws NoModificationAllowedError if the element has no parent. Guarded.
placeholder.outerHTML = "<img src='/logo.svg' alt='Logo'>";
insertAdjacentHTML
insertAdjacentHTML(position, html) — parses html and inserts it at position (case-insensitive): beforebegin, afterbegin, beforeend, afterend. An invalid position throws SyntaxError; beforebegin/afterend on a parentless node are no-ops. Guarded.
list.insertAdjacentHTML("beforeend", "<li>Appended</li>");
classList
element.classList is a live DOMTokenList over the class attribute — the single source of truth (emptying the list removes the attribute). Mutators are guarded. It is iterable ([...classList], Array.from(classList)).
| Member |
Behaviour |
add(...tokens) |
Adds tokens (deduped, order preserved). |
remove(...tokens) |
Removes every listed token. |
toggle(token, force?) → boolean |
Adds/removes; force pins the outcome. Returns whether the token is now present. |
replace(old, new) → boolean |
Replaces old with new (set semantics); returns whether a replacement happened. |
contains(token) → boolean |
Membership test. |
item(index) → string / null |
The token at index (negative → null). |
length |
Token count. |
value (get/set) |
The whole class string. |
el.classList.add("active", "highlight");
el.classList.toggle("open"); // → true (now present)
el.classList.replace("active", "done"); // → true
if (el.classList.contains("done")) { /* … */ }
Element traversal
Element-only navigation (skipping text and comment nodes). Each returns an element or null except the count. See Node for the all-kinds accessors (firstChild, nextSibling, …).
| Accessor |
Value |
children |
A static NodeList of child elements. |
firstElementChild / lastElementChild |
First / last child element, or null. |
childElementCount |
Number of child elements. |
nextElementSibling / previousElementSibling |
Adjacent sibling element, or null. |
for (const row of table.children) { /* each <tr> */ }
closest
closest(selector) → the nearest inclusive ancestor matching the selector, or null. Receiver-scoped. Invalid selector throws SyntaxError.
const form = submitButton.closest("form");
matches
matches(selector) → boolean. Invalid selector throws SyntaxError.
if (el.matches("a[href^='https://']")) { /* external link */ }
Insertion convenience
The WHATWG convenience mutators. String arguments become text nodes. before/after/replaceWith are no-ops on a detached node. All guarded.
| Method |
Behaviour |
append(...nodes) |
Insert at the end of this element's children. |
prepend(...nodes) |
Insert at the start. |
before(...nodes) / after(...nodes) |
Insert as a sibling before / after this element. |
replaceWith(...nodes) |
Replace this element (it detaches but stays live). |
remove() |
Detach this element from its parent. |
heading.after(document.createElement("hr"));
oldBanner.replaceWith("Plain text now"); // string → text node
staleNode.remove();
See also
- Node — tree mutation and all-kinds traversal
- Document — querying and creating elements
- NodeList — what
children/querySelectorAll return
Declarative commands
A declarative command is a command="..." attribute on a <button> that pagelove.mjs recognizes and turns into a schema mutation — creating a new instance or deleting an existing one — without any application code.
When to reach for it
Reach for a declarative command whenever a button should add a new schema instance to a view or remove an existing one. The runtime handles the DOM update and the network call; the markup carries all the intent.
Supported commands
command= value |
What it does |
--create-instance |
Creates a new instance of the schema named by the button's data-schema attribute and appends it to the target element. |
--remove-instance |
Deletes the schema instance referenced by the button's nearest [data-for] ancestor. |
Only these two values are acted on by the command handler. Any other command= value on a button inside the view is ignored.
| Attribute |
Required for |
Purpose |
command |
both |
Names the action. Must be --create-instance or --remove-instance. |
data-schema |
--create-instance |
URL of the schema type to instantiate. |
commandfor |
--create-instance (outside templates) |
ID of the target element the new instance is appended to. |
--remove-instance takes no attributes of its own — it infers its target from the nearest [data-for] ancestor of the button.
pagelove.mjs dispatches command buttons through two delivery paths:
| Path |
Where it fires |
How the button is found |
Native command event |
On the element named by commandfor |
The runtime attaches a command listener to every element referenced by a commandfor on a [command] button at startup. |
Delegated click |
On the view root |
The runtime listens for clicks anywhere inside the view and routes any [command] button that has no commandfor attribute through the same handler. |
The delegated path is what makes commands work inside <template> content, where commandfor cannot point at an element that does not yet exist.
Where the target comes from
For --create-instance:
| Button location |
Target element |
Inside a [data-for] view element |
The schema element whose ID matches [data-for]. |
| Anywhere else |
The element referenced by commandfor (resolved by the native command event). |
For --remove-instance, the target is always the schema element referenced by the nearest [data-for] ancestor. A button with no [data-for] ancestor does nothing.
Inferred itemprop on the new article
After creating the new <article>, pagelove.mjs inspects the target's itemtype. If the target has one, the runtime looks up that schema and searches its property list for a property whose type matches the new instance's type. If a match is found, the new article is given that itemprop. If nothing matches, no itemprop is set.
Optimistic behavior
Both commands update the DOM first and persist in the background.
| Command |
DOM step |
Network step |
--create-instance |
Pagelove.create(typeUrl) builds the article and target.appendChild(article) inserts it immediately. |
target.POST(article) runs in the background when the target supports POST. The promise is stashed as article._pendingPost so later writes can await it. |
--remove-instance |
The schema element's etag is cleared and schemaEl.remove() detaches it immediately. |
DELETE() is called on the detached element if it exposes one. |
Examples
Creating a new note
<main id="canvas" itemscope itemtype="https://schema.host/Board">
<!-- existing notes -->
</main>
<button
command="--create-instance"
commandfor="canvas"
data-schema="https://schema.host/StickyNote">
Add note
</button>
Activating the button creates a StickyNote article and appends it to #canvas. If Board declares a property of type StickyNote, the new article is tagged with that itemprop automatically.
Deleting the current item from inside a template
<template itemtype="https://schema.host/StickyNote">
<article class="sticky">
<h1 data-bind="title" contenteditable></h1>
<button command="--remove-instance">Delete</button>
</article>
</template>
Each stamped view sits inside a [data-for] wrapper pointing at its backing article. Clicking the Delete button removes that article from the DOM and fires DELETE() against it.
See also
HTMLBRElement
The interface for <br>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
Node
Members shared by every node — the document, elements, text, comments, and fragments alike: traversal, tree mutation, character data, and metadata. Element-only navigation (children, firstElementChild, …) is on the Element page. All mutators are guarded and throw NoModificationAllowedError on a read-only document.
Traversal
All-kinds navigation (text and comment nodes are included). Each returns a handle or null.
| Accessor |
Value |
parentNode |
The parent, or null. |
parentElement |
The parent only if it is an element, else null. |
firstChild / lastChild |
First / last child of any kind, or null. |
previousSibling / nextSibling |
Adjacent sibling of any kind, or null. |
childNodes |
A static NodeList of all child kinds. |
ownerDocument |
The owning document — null when called on the document itself. |
hasChildNodes
hasChildNodes() → boolean.
if (node.hasChildNodes()) {
for (const child of node.childNodes) { /* text and elements */ }
}
| Accessor |
Value |
nodeType |
The numeric type code — compare against the Node constants. |
nodeName |
Element = uppercased tag; otherwise #text, #comment, #document, #document-fragment, the doctype name, or a PI target. |
if (node.nodeType === Node.ELEMENT_NODE) { /* it's an element */ }
Character data
textContent
Get concatenates all descendant text (a comment yields its own data). Set replaces every child with a single text node — an empty string leaves no children. Available on every node; guarded.
cell.textContent = "42";
const words = article.textContent.split(/\s+/).length;
data / length
data (get/set) and length (get) are CharacterData members, so they apply to text and comment nodes: data is the character payload, length its Unicode character count. On a node of any other interface they are out of scope, so element.data and element.length are undefined. Setting data is guarded.
const c = document.createComment("draft");
c.data; // "draft"
c.length; // 5
c.data = "final";
Tree mutation
A node from another document is adopted (deep-copied); a DocumentFragment argument moves its children (leaving the fragment empty).
appendChild
appendChild(child) → the appended child. Appending a node to its own descendant or itself throws HierarchyRequestError.
list.appendChild(document.createElement("li"));
insertBefore
insertBefore(node, reference) → the inserted node. A null/omitted reference behaves like appendChild; otherwise reference must be a current child, else NotFoundError.
list.insertBefore(newItem, list.firstChild); // insert at the top
removeChild
removeChild(child) → the removed child (which stays live with parentNode === null). child must be a child, else NotFoundError.
list.removeChild(list.lastChild);
replaceChild
replaceChild(newNode, oldNode) → oldNode. oldNode must be a child, else NotFoundError.
list.replaceChild(document.createElement("li"), staleItem);
cloneNode
cloneNode(deep?) → a detached clone (deep defaults to false). Rejected on a read-only document — the clone would allocate into the read-only arena.
const copy = template.cloneNode(true);
contains
contains(other) → boolean; false across documents.
if (main.contains(node)) { /* node is inside <main> */ }
Node constants
The Node global exposes the standard node-type constants, for comparison against nodeType:
Node.ELEMENT_NODE (1) · Node.TEXT_NODE (3) · Node.COMMENT_NODE (8) · Node.DOCUMENT_NODE (9) · Node.DOCUMENT_TYPE_NODE (10) · Node.DOCUMENT_FRAGMENT_NODE (11)
See also
- Element — attributes, content, and element-only traversal
- Document — creating the nodes you insert
- NodeList — iterating
childNodes
- DOMException — the error type these mutators throw
NodeList
Query results and child lists are a single static NodeList type. There is no separate HTMLCollection — children also returns a NodeList. It is a snapshot taken when produced: later mutations to the tree are not reflected.
A NodeList backs childNodes, children, querySelectorAll, and getElementsByTagNameNS.
Members
| Member |
Behaviour |
length |
The number of nodes. |
item(index) |
The node at index, or null (negative or out-of-range → null). |
It is iterable — for…of, spread, and Array.from all work.
const items = document.querySelectorAll("li");
items.length; // e.g. 3
items.item(0); // first <li>, or null
items.item(-1); // null (no negative indexing)
for (const li of items) {
li.classList.add("counted");
}
const titles = Array.from(items, li => li.textContent);
Because a NodeList is a snapshot, removing a node during iteration does not shorten the list — the snapshot still holds every node that matched when it was produced.
See also
- Node —
childNodes and traversal
- Element —
children, querySelectorAll on an element
- Document —
querySelectorAll, getElementsByTagNameNS
Web Components
A Pagelove Web Component is a real custom element, auto-defined by pagelove.mjs from a <template itemtype> whose root tag is hyphenated, extending the PageloveComponent base class so its light-DOM view stays in sync with its backing schema article.
When to reach for it
Reach for a Web Component when a template is a live, interactive element with its own lifecycle — drag, resize, mixin behavior, or any API the rest of the page will call. Give the template root a hyphenated tag (<sticky-note>, <kanban-card>) and the runtime takes care of the rest.
Auto-defined custom elements
On boot, pagelove.mjs walks every <template itemtype> it has discovered and inspects template.content.firstElementChild. The auto-definition rule is:
| Condition |
Result |
Root tag contains a - and is not already registered |
A class extending PageloveComponent is defined via customElements.define, with static itemtype set to the template's itemtype. |
Root tag contains no - |
Skipped — renders as a plain DOM fragment. |
| Root tag already registered |
Skipped — the existing registration wins, so apps can pre-register subclasses before pagelove.mjs runs. |
| Same tag is the root of two templates with different itemtypes |
The runtime throws — a custom element can only represent one schema type. |
Any mixins whose selectors match the template root are stacked onto the base class before customElements.define is called.
The PageloveComponent base class
PageloveComponent extends HTMLElement. It is an autonomous custom element — not a built-in extension — so the root tag itself is what the browser upgrades.
| Member |
Purpose |
static itemtype |
Set by the auto-definer to the schema itemtype the class represents. null on the unsubclassed base. |
static binders |
Array of binder definitions. Ships with dataBindBinder and dataBindAttrBinder. |
static create(values) |
Factory that calls window.pagelove.create(this.itemtype, values) to build a new schema article. |
connectedCallback() |
Resolves the schema article from data-for, builds a propName → [{element, binder}] index from every binder's collect(), runs an initial bind, then starts a MutationObserver on the schema article. |
disconnectedCallback() |
Disconnects the observer, clears the index, drops the schema article reference. |
_get(propName) / _set(propName, value) |
Read and write schema properties. Used by mixins and subclasses. |
The observer watches childList, subtree, characterData, and attributes (filtered to content and datetime). When a schema property becomes dirty, every indexed entry is re-applied through its binder, so schema writes flow one-way into the view.
The default binders
dataBindBinder collects every [data-bind] element under the component root and writes the named schema property to either element.value (for form controls) or element.textContent (for everything else).
dataBindAttrBinder reads the root's data-bind-attr attribute, splits on whitespace, and forwards each named property onto root.dataset.<propName> so CSS and selectors can react to schema values.
Both binders implement the rules documented on the HTML bindings page — the base class simply runs them inside its own lifecycle.
Mixins
Mixins add behavior to auto-defined components by wrapping the PageloveComponent base class before it is registered. The registry is a module-level array of (selector, mixinFn) pairs.
| Function |
Signature |
Purpose |
registerComponentMixin |
(selector, mixinFn) |
Push a new entry. selector is a CSS selector tested against the template root; mixinFn is a class factory of the form (Base) => class extends Base { … }. |
getMatchingMixins |
(rootElement) |
Return the mixin factories whose selector matches the given root. Rarely called directly — the auto-definer uses it during discovery. |
Stacking order is governed by reduceRight: mixins are applied in reverse registration order, so the earliest-registered mixin sits closest to PageloveComponent and later registrations wrap around it. Each mixin should call super.connectedCallback?.() and super.disconnectedCallback?.().
Built-in mixins
Three mixins ship with the component module and auto-register themselves on import.
| Mixin |
Auto-registered selector |
Reads / writes |
What it does |
Draggable |
[data-draggable] |
writes data-x, data-y |
Pointer-driven positioning. On pointerdown (or inside a [data-drag-handle] descendant if one exists), it tracks the pointer and updates inline left / top for live feedback. On release it writes dataset.x / dataset.y, which the runtime commits to the schema as x / y. |
Resizable |
[data-resizable] |
writes data-width, data-height |
Injects a .pl-resize-handle corner child and drives resize via pointer events. On release it writes dataset.width / dataset.height, which the runtime commits to the schema as width / height. |
Stackable |
[data-stackable] |
writes data-z |
Click-to-front z-ordering. On pointerdown (capture phase, non-intrusive), it sets data-z to one more than the maximum data-z of its siblings, which the runtime commits to the schema as z. |
Stackable also mirrors its data-z attribute to inline style.zIndex on connection and whenever the attribute changes. This keeps the stacking applied without depending on CSS attr(data-z integer), which Safari does not yet support.
Examples
Minimal custom element from a template
<template itemtype="https://schema.host/StickyNote">
<sticky-note>
<h1 data-bind="title" contenteditable></h1>
<p data-bind="body" contenteditable></p>
</sticky-note>
</template>
The root is hyphenated, so pagelove.mjs defines <sticky-note> as a PageloveComponent subclass. Each stamped instance binds title and body through dataBindBinder.
Draggable, resizable, and stackable without writing any JavaScript
<template itemtype="https://schema.host/StickyNote">
<sticky-note data-draggable data-resizable data-stackable>
<h1 data-bind="title" contenteditable></h1>
<p data-bind="body" contenteditable></p>
</sticky-note>
</template>
All three built-in selectors match the template root, so the auto-definer stacks Draggable, Resizable, and Stackable onto PageloveComponent. Dragging the note commits x and y to the schema; dragging the corner handle commits width and height; clicking the note raises z so it sits above its siblings.
A custom mixin
import { registerComponentMixin } from 'https://pagelove.github.io/beta-js/pagelove/component.mjs';
registerComponentMixin('[data-glow]', (Base) => class extends Base {
connectedCallback() {
super.connectedCallback?.();
this.addEventListener('pointerenter', () => this.classList.add('glowing'));
this.addEventListener('pointerleave', () => this.classList.remove('glowing'));
}
disconnectedCallback() {
super.disconnectedCallback?.();
this.classList.remove('glowing');
}
});
Any template root that matches [data-glow] now gets hover-glow behavior as part of its class chain, provided registration happens before pagelove.mjs discovers templates.
See also
- The Pagelove class — the runtime that discovers templates and calls the component auto-definer.
- HTML bindings — the binding rules implemented by the default
dataBindBinder and dataBindAttrBinder.
- Declarative commands —
--create-instance and --remove-instance buttons hosted inside template-defined components.
HTMLBaseElement
The interface for <base>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
href |
href |
string |
Reflects verbatim — no base-URL resolution. |
target |
target |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
DOMParser and XMLSerializer
DOMParser and XMLSerializer
Two globals for moving between HTML strings and DOM: parse a fresh writable document, and serialise any node back to a string.
DOMParser
parseFromString
new DOMParser().parseFromString(html, type) → a writable document. This is the way to build markup to return from a read-only binding context: the parsed document (and everything reached from it) is writable even when the ambient document is not.
Divergence: the type argument is accepted but ignored — input is always parsed as text/html.
export default () => {
const d = new DOMParser().parseFromString("<ul></ul>", "text/html");
const li = d.createElement("li");
li.textContent = "Item";
d.querySelector("ul").appendChild(li);
return d.querySelector("ul"); // return an element to splice in
};
XMLSerializer
serializeToString
new XMLSerializer().serializeToString(node) → a string. A document serialises whole; any other node serialises as its outer HTML (a fragment emits just its children).
const html = new XMLSerializer().serializeToString(element);
Serialising is rarely needed inside a binding — returning an element splices it into the page directly (see Returning DOM from a binding). Reach for serializeToString when you need the markup as a string — for example to hash it, store it in an attribute, or compare two subtrees.
See also
The Pagelove class
Pagelove is the class that drives declarative HTML apps. Most pages don't construct it explicitly — the library auto-instantiates one on <main> at load time.
When to reach for it
Reach for the constructor directly when an app needs explicit lifecycle control, multiple view roots, commit hooks, a filtered subset of schema instances, or when Pagelove must be driven from application code instead of from the auto-start.
Loading the library
Import the module from wherever it is served:
<script type="module">
import { Pagelove } from 'https://pagelove.github.io/beta-js/pagelove.mjs';
</script>
Merely loading pagelove.mjs is usually enough — the auto-start handles construction. See the JavaScript overview for the full loading story.
Auto-start
When the module finishes loading, it awaits ready and then checks the document. If the page has a <main> element and no Pagelove instance has been constructed by application code (_instanceCount === 0), the library runs:
document.pagelove = new Pagelove({ view: main });
await document.pagelove.start();
The instance is then reachable as document.pagelove. Auto-start is skipped if there is no <main>, or if any application code has already called new Pagelove(...) before the ready promise resolves.
Constructor
new Pagelove(config)
The single argument is a config object. Every option is read once at construction time.
| Option |
Type |
Required |
Description |
view |
Element |
required |
The visible view root. Typically <main>. All rendered instances are appended here. |
filter |
string |
optional |
CSS selector that limits which discovered schema instances this Pagelove manages. |
schema |
Element |
optional (legacy) |
Explicit schema root element. Direct [itemscope][itemtype][id] children are scanned. Prefer filter in new code. |
beforeCommit |
(schemaEl, prop, value) => boolean |
optional |
Called before every write. Return false to reject the write. |
afterCommit |
(schemaEl, prop, value) => void |
optional |
Called after every successful write. |
onRender |
(viewEl, schemaEl) => void |
optional |
Called after a template stamp has been populated from a schema article. |
onPatch |
({ articleId, prop }) => void |
optional |
Called when a remote patch is applied to a schema article. |
ensureSchemaEl |
(article, prop, value) => Element |
optional |
Overrides the default routine that locates or creates the [itemprop] element a write should target. |
The most-recently-constructed instance is also assigned to window.pagelove so that PageloveComponent.create can delegate into it.
Methods
start()
await pagelove.start();
Discovers <template itemtype> definitions, awaits the ready promise, performs the first full render, and begins observing the document for changes. Idempotent — calling it on an already-started instance is a no-op. Returns a promise that resolves once observation is in place.
stop()
pagelove.stop();
Disconnects every observer and removes the change, focusout, and input listeners. Use it when tearing down a Pagelove-driven region without unloading the page.
populate(viewEl, schemaId)
pagelove.populate(dialog, 'item-abc123');
Populates the [data-bind] children of viewEl from the schema article whose id is schemaId, and sets viewEl.dataset.for so subsequent commits route back to that article. Use it for dialogs, side panels, or any element outside the main view. The original innerHTML is captured on first call and restored on every subsequent call, so the same element can host different schema articles in turn.
renderAll()
pagelove.renderAll();
Forces a full re-render of the view from the current schema. Existing rendered children of the view (those carrying [data-for]) are removed, and every discovered schema instance is re-stamped through its template. Schema articles that coexist inside the view are preserved.
create(typeUrl, values = {})
const article = pagelove.create('https://schema.host/MoodNote', { mood: 'curious' });
Builds a new <article> element for the named schema type, populated from values and from any defaults declared in the schema definition. The returned article carries itemscope, itemtype, a generated id, and an [itemprop] child for every defined property. Throws if no schema definition has been discovered for typeUrl.
flushPendingPatches()
pagelove.flushPendingPatches();
Applies every patch that was deferred because its target element was focused at the time. Pagelove defers remote patches to focused inputs to avoid clobbering in-flight edits; this method drains the queue on demand.
Properties
hasPendingPatches
Read-only boolean getter. Returns true when at least one remote patch has been deferred and is waiting to be applied. Pair with flushPendingPatches() for explicit drain control.
Module exports
| Export |
What it is |
Pagelove |
The class documented on this page. |
ReactiveTemplate |
Backward-compat alias for Pagelove. New code should import Pagelove. |
PageloveComponent |
Base class for Web Components, re-exported from pagelove/component.mjs. |
Draggable |
Drag-and-drop mixin, re-exported from pagelove/component.mjs. |
registerComponentMixin |
Mixin registration helper, re-exported from pagelove/component.mjs. |
ready |
Promise that resolves when the initial OPTIONS discovery completes. Awaited by start() and by the auto-start. |
Examples
Explicit instantiation
<main></main>
<aside id="inbox"></aside>
<script type="module">
import { Pagelove } from 'https://pagelove.github.io/beta-js/pagelove.mjs';
const pagelove = new Pagelove({
view: document.querySelector('#inbox'),
filter: '[data-folder="inbox"]',
});
await pagelove.start();
</script>
A second view root is mounted on #inbox, restricted to schema instances tagged with data-folder="inbox". The default auto-start is suppressed because the application constructed an instance before ready resolved.
Intercepting writes with beforeCommit
const pagelove = new Pagelove({
view: document.querySelector('main'),
beforeCommit(schemaEl, prop, value) {
if (prop === 'title' && value.trim() === '') {
return false; // reject empty titles
}
return true;
},
afterCommit(schemaEl, prop, value) {
console.log('committed', schemaEl.id, prop, value);
},
});
await pagelove.start();
beforeCommit runs against every prospective write. Returning false cancels the commit; returning anything truthy lets it proceed and triggers afterCommit once the write succeeds.
See also
HTMLBodyElement
The interface for <body>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
Server-Sent Events
PageloveSSE is the live mutation streaming client: it opens a Server-Sent Events connection to a document, parses incoming HTML Microdata mutation events, applies them to the live DOM, and re-dispatches them as cancelable custom events on document.
When to reach for it
Reach for it when a view should update in real time as the underlying document changes — collaborative editing, live dashboards, multi-tab synchronization — without polling. For the default case, no application code is required at all: importing the module is enough.
Loading the library
Add the module to the page:
<script type="module" src="https://pagelove.github.io/beta-js/pagelove/sse.mjs"></script>
Importing pagelove/sse.mjs auto-instantiates one PageloveSSE subscribed to the current page URL. The default instance is held internally and begins streaming as soon as the module evaluates. Application code is only needed when subscribing to a different URL or when intercepting events.
The PageloveSSE class
import { PageloveSSE } from 'https://pagelove.github.io/beta-js/pagelove/sse.mjs';
Constructors
| Form |
Subscription target |
new PageloveSSE() |
window.location.href — the current page |
new PageloveSSE(url) |
The given document URL |
The constructor opens the underlying EventSource immediately, with withCredentials: true so cookies and authorization travel with the request.
Methods
| Method |
Description |
close() |
Close the underlying EventSource and drop the reference. The instance cannot be reopened — construct a new one to resubscribe. |
Properties
| Property |
Type |
Description |
url |
string |
The URL this client is subscribed to. Read-only. |
source |
EventSource | null |
The underlying EventSource, or null after close(). Read-only. |
Static methods
| Method |
Description |
PageloveSSE.parse(data) |
Parse an HTML Microdata mutation payload. Returns { method, selector, path, host, body, etag } or null. |
PageloveSSE.parseReset(data) |
Parse a reset payload. Returns the reason string, or "unknown" if no reason is present. |
DOM mutations
When a mutation event arrives, PageloveSSE locates the target with the carried CSS selector and applies the change:
| Method |
Action |
POST |
Appends the new content as a child of the matched element. |
PUT |
Replaces the matched element with the new content. |
DELETE |
Removes the matched element. |
If no element matches the selector, the event is silently dropped. Mutations that echo a local write (matched against the pending PLMethodStarted queue) are recognized as echoes and the DOM step is skipped — the local change already produced the result.
This local echo check only reconciles the same tab's own optimistic write against the mutation event that write eventually produces — it does not affect which events the server delivers. PageloveSSE connects with a plain EventSource and does not currently read the server-assigned connection token or send it back on writes (see Echo suppression), so the server falls back to its session-based suppression: a write from one browser tab is not delivered live to another tab of the same session, since same-origin tabs share the session cookie. Each tab only ever sees its own writes reflected through this local echo-matching step, not through the SSE stream. If your application needs one tab to see another same-session tab's live writes, subscribe with your own EventSource, listen for the pagelove-connection event to capture the server-assigned token, and send it back as a Pagelove-Connection header on every mutating request from that tab, as described in that section, rather than relying on the default PageloveSSE connection.
Events on document
Three custom events are dispatched on document. All three bubble and are composed.
| Event |
When it fires |
Cancelable |
event.detail contains |
PLMutation |
Before a parsed mutation is applied to the DOM |
yes — preventDefault() skips the DOM change |
method, selector, path, host, body, etag, element |
PLMutationApplied |
After the mutation has been applied |
no |
Same shape as PLMutation. element is the new or modified node, or null for DELETE. |
PLStreamReset |
When the server sends a reset event |
yes — preventDefault() suppresses the default location.reload() |
reason |
PLMutation detail fields:
| Field |
Type |
Description |
method |
string |
HTTP method — POST, PUT, or DELETE. |
selector |
string |
CSS selector of the target element. |
body |
string |
HTML fragment to apply. Empty for DELETE. |
path |
string |
Document path the mutation belongs to. |
host |
string |
Virtual host the mutation belongs to. |
etag |
string |
ETag of the resulting element, when supplied. |
element |
Element |
The DOM element matched by the selector. |
Listening for events
document.addEventListener('PLMutation', (event) => {
const { method, selector, element } = event.detail;
console.log(`incoming ${method} ${selector}`);
// event.preventDefault(); // would skip the DOM change
});
PLMutationApplied follows the same shape and fires after the change has landed. PLStreamReset carries event.detail.reason; calling preventDefault() cancels the automatic reload.
Focus protection
Focus protection — deferring incoming changes that target the currently focused element until focus leaves — is not implemented in pagelove/sse.mjs. It lives in the Pagelove class, which observes the schema, queues patches against focused inputs, and exposes flushPendingPatches() and hasPendingPatches for explicit control.
Examples
Default — include the script
<script type="module" src="https://pagelove.github.io/beta-js/pagelove/sse.mjs"></script>
The page is now live. Any mutation the server streams for this URL is applied to the DOM as it arrives.
Manual subscription to a different URL
<script type="module">
import { PageloveSSE } from 'https://pagelove.github.io/beta-js/pagelove/sse.mjs';
const sidebar = new PageloveSSE('/sidebar.html');
document.addEventListener('PLMutationApplied', (event) => {
if (event.detail.path === '/sidebar.html') {
console.log('sidebar updated', event.detail.selector);
}
});
// Later, when the sidebar is dismissed:
// sidebar.close();
</script>
A second subscription is opened against /sidebar.html alongside the auto-instantiated default. Both feed events to the same document listeners; consumers distinguish them by event.detail.path.
See also
DOMException
Every error thrown by the DOM API — a guarded mutation on a read-only document, an invalid selector, a hierarchy violation — is a DOMException instance. The constructor is also available directly, for a binding that wants to raise its own DOM-shaped error.
Constructor
new DOMException(message?, name?)
| Parameter |
Default |
Description |
message |
"" |
Human-readable description. |
name |
"Error" |
The error name — one of the standard names below, or any custom string. |
throw new DOMException("no matching element", "NotFoundError");
Members
| Member |
Value |
name |
The name passed to the constructor ("Error" if omitted). |
message |
The message passed to the constructor ("" if omitted). |
code |
The legacy numeric code for name, or 0 if name is not one of the recognised legacy names. |
toString
toString() → "DOMException: <name>", or "DOMException: <name>: <message>" when message is non-empty.
try {
card.setAttribute("id", "x"); // card is read-only
} catch (e) {
e instanceof DOMException; // true
e.name; // "NoModificationAllowedError"
e.code; // 7
e.toString(); // "DOMException: NoModificationAllowedError: document is read-only in this binding context"
}
Name and legacy code
code reflects the Web IDL legacy error code for the recognised name values:
name |
code |
IndexSizeError |
1 |
DOMStringSizeError |
2 |
HierarchyRequestError |
3 |
WrongDocumentError |
4 |
InvalidCharacterError |
5 |
NoDataAllowedError |
6 |
NoModificationAllowedError |
7 |
NotFoundError |
8 |
NotSupportedError |
9 |
InUseAttributeError |
10 |
InvalidStateError |
11 |
SyntaxError |
12 |
InvalidModificationError |
13 |
NamespaceError |
14 |
InvalidAccessError |
15 |
ValidationError |
16 |
TypeMismatchError |
17 |
SecurityError |
18 |
NetworkError |
19 |
AbortError |
20 |
URLMismatchError |
21 |
QuotaExceededError |
22 |
TimeoutError |
23 |
InvalidNodeTypeError |
24 |
DataCloneError |
25 |
Any other name (including the default "Error") yields code === 0.
Names raised by this API
The DOM API overview lists the specific name values this implementation actually throws — SyntaxError, HierarchyRequestError, NotFoundError, NamespaceError, and NoModificationAllowedError — and the conditions that raise each one.
See also
- JavaScript DOM API — which names this API raises, and when
- Node — the tree mutations that are guarded on a read-only document
The interface for <button>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
type |
type |
enum |
Keywords: submit · reset · button. Missing → "submit"; invalid → "submit". |
name |
name |
string |
Reflects the content attribute verbatim. |
value |
value |
string |
Reflects the content attribute verbatim. |
disabled |
disabled |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
Primitives
pagelove/primitives.mjs is the low-level HTTP client that pagelove.mjs uses internally. Most apps do not touch it directly.
When to reach for it
- Tooling that talks to Pagelove without rendering a page.
- Scripts that issue requests outside the declarative binding flow.
- Custom integrations where full control over the request lifecycle is needed.
For everything else, use the Pagelove class and the declarative flow on top.
Loading the library
<script type="module">
import { PLDocument, PLElement } from 'https://pagelove.github.io/beta-js/pagelove/primitives.mjs';
</script>
The module exports two classes: PLDocument and PLElement.
The PLDocument class
A PLDocument represents a Pagelove resource URL and the live DOM associated with it.
Constructor
| Form |
Bound document |
new PLDocument() |
window.location.href — bound to window.document |
new PLDocument(url) |
The given URL. If it matches window.location.href, the live document is bound; otherwise the document is fetched and parsed lazily. |
Methods
| Method |
Description |
OPTIONS() |
Issues an OPTIONS request with Accept: multipart/mixed, parses the multipart response, and dispatches a PLCapability event on every node matching a declared selector. |
createElement(element) |
Returns a new PLElement wrapping the given DOM node. |
req(method, ...opts) |
Returns a bare Request targeting the document URL. |
Properties
| Property |
Type |
Description |
url |
string |
The URL this document is bound to. |
document |
Promise<Document> |
Resolves to the bound DOM document. Fetches and parses the HTML on first access if no live document is bound. |
A PLDocument bound to a live Document stores a WeakRef to itself on document.pagelove and installs listeners for PLCapability and PLMethodCompleted.
The PLElement class
A PLElement wraps a single DOM node and knows how to issue HTTP requests scoped to that node.
Constructor
| Form |
Effect |
new PLElement(url) |
Creates an element bound to the URL with no DOM node attached yet. |
new PLElement(url, element) |
Binds to the given DOM node. The element's ownerDocument becomes the associated document. |
Methods
| Method |
Description |
GET() |
Fetches the element fragment, parses the response body as a single HTML node, and returns the new node. |
PUT(body?) |
Replaces the element on the server. Body defaults to element.outerHTML; a Node body is serialized via outerHTML. Returns the raw Response. |
POST(body) |
Posts a child fragment. The response body is parsed as a single HTML node and appended as a child of the wrapped element (unless the supplied body was already a live attached node). Throws if no body is supplied. |
DELETE() |
Deletes the element on the server and removes it from the DOM on success. |
req(method, opts) |
Builds the underlying Request object — sets the Range header, conditionally sets If-Match, and merges the caller's opts. |
Properties
| Property |
Type |
Description |
url |
string |
The document URL the element is scoped against. |
element |
Element |
The wrapped DOM node. Setting it also sets document from the node's ownerDocument. |
document |
Document |
The DOM document the wrapped element belongs to. |
selector |
string |
A stable CSS selector generated from the element. Prefers id, anchors to the nearest ancestor with an id, and falls back through itemprop, class names, role, and :nth-child(...). |
OPTIONS lives on PLDocument, not PLElement — discovery is document-level.
Attached methods on DOM elements
PLDocument listens for PLCapability events on its bound document. The event payload looks like:
{
selector: '<css selector>',
allow: ['GET', 'PUT', 'POST', 'DELETE']
}
For each method named in allow, the document constructs a PLElement for the event target and attaches the matching method directly to the DOM node as a non-writable, configurable property:
Object.defineProperty(target, 'PUT', { value: plElement.PUT.bind(plElement), ... });
After the flow has run, element.GET(), element.PUT(body), element.POST(body), and element.DELETE() are callable on the DOM node itself with no further imports. Only methods the server has authorized appear.
ETag handling
ETags are loaded lazily, only for elements that need them.
- When a
PLCapability event arrives for an element with an id and etag === undefined, PLDocument registers the element with a shared IntersectionObserver (rootMargin: '200px').
- When the element scrolls into view, the observer issues a
HEAD request with Range: selector=<element selector> and stashes the response's ETag header on the element as element.etag.
- Successful method requests also update
element.etag from the response's ETag header. After a POST, the parent's previous ETag is restored and the response ETag is assigned to the new child instead.
Every request a PLElement issues is built by req(method, opts):
| Header |
Value |
When |
Range |
selector=<generated-selector> |
Always |
If-Match |
<element.etag> |
When element.etag is a string and the method is not POST |
Everything else is a standard fetch() Request. Each request also dispatches PLMethodStarted before sending and PLMethodCompleted after the response arrives. Both events bubble and carry { method, selector }; PLMethodCompleted additionally carries response.
Examples
Calling an attached method
<script type="module">
import { PLDocument } from 'https://pagelove.github.io/beta-js/pagelove/primitives.mjs';
const doc = new PLDocument();
await doc.OPTIONS();
document.addEventListener('click', async (event) => {
const card = event.target.closest('article.note');
if (card && typeof card.DELETE === 'function') {
await card.DELETE();
}
});
</script>
Once OPTIONS() has run, any matching <article class="note"> exposes the methods the server allows.
Manual PLDocument and PLElement
<script type="module">
import { PLDocument } from 'https://pagelove.github.io/beta-js/pagelove/primitives.mjs';
const doc = new PLDocument('/notes.html');
const target = document.getElementById('note-42');
const note = await doc.createElement(target);
await note.PUT('<article id="note-42">Edited</article>');
</script>
The wrapper is constructed by hand and no capability discovery is required. Range: selector=#note-42 is generated from the element's id; If-Match is added automatically once note.element.etag is populated.
See also
- The Pagelove class — the high-level API that sits on top of primitives.
OPTIONS method — the multipart capability discovery mechanism OPTIONS() consumes.
PUT method — the Range: selector=... and If-Match headers in detail.
HTMLCanvasElement
The interface for <canvas>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
width |
width |
number |
unset → 300. |
height |
height |
number |
unset → 150. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
Debug channels
pagelove/debug.mjs provides bitwise debug channels for module-level console logging. Channels can be toggled at runtime from devtools and persist across page reloads.
When to reach for it
Reach for it to diagnose problems with SSE mutation streaming, HTTP requests and method attachment, or schema discovery and template registration. Each channel gates logs for one area of the system. Enable channels from devtools without reloading, set a breakpoint, and observe which channel is running.
Channels
The module exports four channel constants. Enable channels by bitwise OR:
| Constant |
Bit |
Covers |
Pagelove.SSE |
1 << 0 |
Mutation streaming, event reception, reconnection |
Pagelove.PRIMITIVES |
1 << 1 |
HTTP requests, OPTIONS discovery, method attachment |
Pagelove.SCHEMA |
1 << 2 |
Schema discovery, template registration, component definition |
Pagelove.ALL |
~0 |
Every channel enabled |
Enabling and disabling channels
Enable or disable channels with the Pagelove.debug getter/setter. To enable the SSE channel:
Pagelove.debug |= Pagelove.SSE;
Enable multiple channels at once:
Pagelove.debug = Pagelove.SSE | Pagelove.PRIMITIVES;
Enable everything:
Pagelove.debug = Pagelove.ALL;
Silence all channels:
Pagelove.debug = 0;
The mask is treated as an integer. Setting debug to a non-integer value is coerced to an int via bitwise OR with zero.
Persistence
The active channel mask is stored in localStorage.pagelove_debug when available. The mask restores automatically when the module loads, so debug settings survive page reloads and browser restarts. If localStorage is unavailable — such as in private browsing mode with storage disabled — persistence is silently skipped and the mask starts at 0.
Logging methods
Three methods gate console output against the active channel mask:
| Method |
Behavior |
Pagelove.log(channel, ...args) |
Calls console.log(...args) only if (Pagelove.debug & channel) !== 0 |
Pagelove.warn(channel, ...args) |
Calls console.warn(...args) under the same gating |
Pagelove.error(channel, ...args) |
Calls console.error(...args) under the same gating |
The first argument is always the channel constant; remaining arguments are passed to the console method unchanged.
Global exposure
When loaded in a browser, the module assigns itself to window.Pagelove so the debug mask can be toggled from devtools without requiring an import statement.
Examples
In the browser console:
Pagelove.debug |= Pagelove.SSE;
All log, warn, and error calls gated on Pagelove.SSE now appear in the console. Reload the page and the setting persists.
Logging from application code
Application modules can participate in the same gating:
import { Pagelove } from 'https://pagelove.github.io/beta-js/pagelove/debug.mjs';
function handleSSEEvent(event) {
Pagelove.log(Pagelove.SSE, '[my-feature]', 'event received', event);
}
The log only appears when the SSE channel is enabled via Pagelove.debug |= Pagelove.SSE.
See also
HTMLDListElement
The interface for <dl>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLDataElement
The interface for <data>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
value |
value |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLDataListElement
The interface for <datalist>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLDetailsElement
The interface for <details>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
open |
open |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLDialogElement
The interface for <dialog>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
open |
open |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLDirectoryElement
The interface for <dir>. Extends HTMLElement → Element.
Deprecated. HTMLDirectoryElement covers an obsolete element (WHATWG HTML §16.3 "Other elements, attributes and APIs"); it exists only for instanceof / constructor.name fidelity and content-attribute reflection, not for use in new content.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
compact |
compact |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLDivElement
The interface for <div>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLElement
The base interface for every HTML element. A tag with no more specific interface below is a plain HTMLElement. Extends Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
dir |
dir |
enum |
Keywords: ltr · rtl · auto. Missing or invalid → "". |
inputMode |
inputmode |
enum |
Keywords: none · text · tel · url · email · numeric · decimal · search. Missing or invalid → "". |
enterKeyHint |
enterkeyhint |
enum |
Keywords: enter · done · go · next · previous · search · send. Missing or invalid → "". |
autocapitalize |
autocapitalize |
enum |
Keywords: "" · off · none · on · sentences · words · characters. off→none and on→sentences are synonyms; missing or present-empty → ""; any other invalid value → "sentences" (the WHATWG Sentences default, matching Chrome). |
contentEditable |
contenteditable |
string, read/write (bespoke accessor) |
Getter returns "true" / "false" / "plaintext-only" / "inherit" (missing or invalid → "inherit", present-empty → "true"). Setter accepts only those four keywords case-insensitively — "inherit" removes the attribute, any other value throws SyntaxError. |
isContentEditable |
(computed) |
boolean, read-only |
Walks ancestors: the nearest ancestor (inclusive) with a defined contentEditable state of true/plaintext-only → editable; false → not editable; none found → false. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLEmbedElement
The interface for <embed>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
src |
src |
string |
Reflects verbatim — no base-URL resolution. |
type |
type |
string |
Reflects the content attribute verbatim. |
width |
width |
string |
Reflects the content attribute verbatim. |
height |
height |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLFieldSetElement
The interface for <fieldset>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
disabled |
disabled |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
name |
name |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLFontElement
The interface for <font>. Extends HTMLElement → Element.
Deprecated. HTMLFontElement covers an obsolete element (WHATWG HTML §16.3 "Other elements, attributes and APIs"); it exists only for instanceof / constructor.name fidelity and content-attribute reflection, not for use in new content.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
color |
color |
string |
Reflects the content attribute verbatim. |
face |
face |
string |
Reflects the content attribute verbatim. |
size |
size |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
The interface for <form>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
action |
action |
string |
Reflects the content attribute verbatim. |
method |
method |
enum |
Keywords: get · post · dialog. Missing → "get"; invalid → "get". |
name |
name |
string |
Reflects the content attribute verbatim. |
target |
target |
string |
Reflects the content attribute verbatim. |
enctype |
enctype |
enum |
Keywords: application/x-www-form-urlencoded · multipart/form-data · text/plain. Missing → "application/x-www-form-urlencoded"; invalid → "application/x-www-form-urlencoded". |
acceptCharset |
accept-charset |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLFrameElement
The interface for <frame>. Extends HTMLElement → Element.
Deprecated. HTMLFrameElement covers an obsolete element (WHATWG HTML §16.3 "Other elements, attributes and APIs"); it exists only for instanceof / constructor.name fidelity and content-attribute reflection, not for use in new content.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
name |
name |
string |
Reflects the content attribute verbatim. |
scrolling |
scrolling |
string |
Reflects the content attribute verbatim. |
src |
src |
string |
Reflects verbatim — no base-URL resolution. |
frameBorder |
frameborder |
string |
Reflects the content attribute verbatim. |
longDesc |
longdesc |
string |
Reflects the content attribute verbatim. |
noResize |
noresize |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
marginHeight |
marginheight |
string |
Reflects the content attribute verbatim. |
marginWidth |
marginwidth |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLFrameSetElement
The interface for <frameset>. Extends HTMLElement → Element.
Deprecated. HTMLFrameSetElement covers an obsolete element (WHATWG HTML §16.3 "Other elements, attributes and APIs"); it exists only for instanceof / constructor.name fidelity and content-attribute reflection, not for use in new content.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
cols |
cols |
string |
Reflects the content attribute verbatim. |
rows |
rows |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLHRElement
The interface for <hr>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLHeadElement
The interface for <head>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLHeadingElement
The interface shared by <h1>, <h2>, <h3>, <h4>, <h5>, <h6>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLHtmlElement
The interface for <html>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLIFrameElement
The interface for <iframe>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
src |
src |
string |
Reflects verbatim — no base-URL resolution. |
srcdoc |
srcdoc |
string |
Reflects the content attribute verbatim. |
name |
name |
string |
Reflects the content attribute verbatim. |
width |
width |
string |
Reflects the content attribute verbatim. |
height |
height |
string |
Reflects the content attribute verbatim. |
allow |
allow |
string |
Reflects the content attribute verbatim. |
loading |
loading |
enum |
Keywords: lazy · eager. Missing → "eager"; invalid → "eager". |
referrerPolicy |
referrerpolicy |
enum |
Keywords: "" · no-referrer · no-referrer-when-downgrade · same-origin · origin · strict-origin · origin-when-cross-origin · strict-origin-when-cross-origin · unsafe-url. Missing → ""; invalid → "". |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLImageElement
The interface for <img>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
src |
src |
string |
Reflects verbatim — no base-URL resolution. |
alt |
alt |
string |
Reflects the content attribute verbatim. |
width |
width |
number |
unset → 0. |
height |
height |
number |
unset → 0. |
srcset |
srcset |
string |
Reflects the content attribute verbatim. |
sizes |
sizes |
string |
Reflects the content attribute verbatim. |
loading |
loading |
enum |
Keywords: lazy · eager. Missing → "eager"; invalid → "eager". |
decoding |
decoding |
enum |
Keywords: sync · async · auto. Missing → "auto"; invalid → "auto". |
crossOrigin |
crossorigin |
nullable enum |
Keywords: anonymous · use-credentials. Missing attribute → null; any other present value → "anonymous"; assigning null removes the attribute. |
referrerPolicy |
referrerpolicy |
enum |
Keywords: "" · no-referrer · no-referrer-when-downgrade · same-origin · origin · strict-origin · origin-when-cross-origin · strict-origin-when-cross-origin · unsafe-url. Missing → ""; invalid → "". |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
The interface for <input>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
type |
type |
enum |
Keywords: text · search · tel · url · email · password · date · month · week · time · datetime-local · number · range · color · checkbox · radio · file · submit · image · reset · button · hidden. Missing → "text"; invalid → "text". |
name |
name |
string |
Reflects the content attribute verbatim. |
value |
value |
string |
Reflects the content attribute (the browser's defaultValue) — not live editing state, since the server DOM is static. |
placeholder |
placeholder |
string |
Reflects the content attribute verbatim. |
required |
required |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
disabled |
disabled |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
readOnly |
readonly |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
checked |
checked |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
min |
min |
string |
Reflects the content attribute verbatim. |
max |
max |
string |
Reflects the content attribute verbatim. |
step |
step |
string |
Reflects the content attribute verbatim. |
pattern |
pattern |
string |
Reflects the content attribute verbatim. |
autocomplete |
autocomplete |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLLIElement
The interface for <li>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
value |
value |
number |
unset → 0; negative values allowed. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLLabelElement
The interface for <label>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
htmlFor |
for |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLLegendElement
The interface for <legend>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLLinkElement
The interface for <link>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
href |
href |
string |
Reflects verbatim — no base-URL resolution. |
rel |
rel |
string |
Reflects the content attribute verbatim. |
type |
type |
string |
Reflects the content attribute verbatim. |
media |
media |
string |
Reflects the content attribute verbatim. |
as |
as |
string |
Reflects the content attribute verbatim. |
crossOrigin |
crossorigin |
nullable enum |
Keywords: anonymous · use-credentials. Missing attribute → null; any other present value → "anonymous"; assigning null removes the attribute. |
referrerPolicy |
referrerpolicy |
enum |
Keywords: "" · no-referrer · no-referrer-when-downgrade · same-origin · origin · strict-origin · origin-when-cross-origin · strict-origin-when-cross-origin · unsafe-url. Missing → ""; invalid → "". |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLMapElement
The interface for <map>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
name |
name |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLMarqueeElement
The interface for <marquee>. Extends HTMLElement → Element.
Deprecated. HTMLMarqueeElement covers an obsolete element (WHATWG HTML §16.3 "Other elements, attributes and APIs"); it exists only for instanceof / constructor.name fidelity and content-attribute reflection, not for use in new content.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
behavior |
behavior |
string |
Reflects the content attribute verbatim. |
bgColor |
bgcolor |
string |
Reflects the content attribute verbatim. |
direction |
direction |
string |
Reflects the content attribute verbatim. |
height |
height |
string |
Reflects the content attribute verbatim. |
hspace |
hspace |
string |
Reflects the content attribute verbatim. |
loop |
loop |
string |
Reflects the content attribute verbatim. |
scrollAmount |
scrollamount |
string |
Reflects the content attribute verbatim. |
scrollDelay |
scrolldelay |
string |
Reflects the content attribute verbatim. |
trueSpeed |
truespeed |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
vspace |
vspace |
string |
Reflects the content attribute verbatim. |
width |
width |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
An abstract interface — no tag creates one directly. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
src |
src |
string |
Reflects verbatim — no base-URL resolution. |
crossOrigin |
crossorigin |
nullable enum |
Keywords: anonymous · use-credentials. Missing attribute → null; any other present value → "anonymous"; assigning null removes the attribute. |
preload |
preload |
string |
Reflects the content attribute verbatim. |
autoplay |
autoplay |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
loop |
loop |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
controls |
controls |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
The interface for <menu>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
The interface for <meta>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
name |
name |
string |
Reflects the content attribute verbatim. |
content |
content |
string |
Reflects the content attribute verbatim. |
httpEquiv |
http-equiv |
string |
Reflects the content attribute verbatim. |
charset |
charset |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLMeterElement
The interface for <meter>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
value |
value |
number, read/write |
Unset → 0; clamped to [min, max]. |
min |
min |
number, read/write |
Unset → 0. |
max |
max |
number, read/write |
Unset → 1, and never below min. |
low |
low |
number, read/write |
Unset → min; clamped to [min, max]. |
high |
high |
number, read/write |
Unset → max; clamped to [low, max]. |
optimum |
optimum |
number, read/write |
Unset → the midpoint of min and max; clamped to [min, max]. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLModElement
The interface shared by <ins>, <del>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
cite |
cite |
string |
Reflects the content attribute verbatim. |
dateTime |
datetime |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLOListElement
The interface for <ol>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
reversed |
reversed |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
start |
start |
number |
unset → 1; negative values allowed. |
type |
type |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLObjectElement
The interface for <object>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
data |
data |
string |
Reflects the content attribute verbatim. |
type |
type |
string |
Reflects the content attribute verbatim. |
name |
name |
string |
Reflects the content attribute verbatim. |
width |
width |
string |
Reflects the content attribute verbatim. |
height |
height |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLOptGroupElement
The interface for <optgroup>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
disabled |
disabled |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
label |
label |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLOptionElement
The interface for <option>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
value |
value |
string |
Reflects the content attribute (the browser's defaultValue) — not live editing state, since the server DOM is static. |
label |
label |
string |
Reflects the content attribute verbatim. |
selected |
selected |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
disabled |
disabled |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLOutputElement
The interface for <output>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
name |
name |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLParagraphElement
The interface for <p>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLParamElement
The interface for <param>. Extends HTMLElement → Element.
Deprecated. HTMLParamElement covers an obsolete element (WHATWG HTML §16.3 "Other elements, attributes and APIs"); it exists only for instanceof / constructor.name fidelity and content-attribute reflection, not for use in new content.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
name |
name |
string |
Reflects the content attribute verbatim. |
value |
value |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLPictureElement
The interface for <picture>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLPreElement
The interface for <pre>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLProgressElement
The interface for <progress>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
value |
value |
number, read/write |
Unset or negative → 0; clamped to [0, max]. |
max |
max |
number, read/write |
Unset or non-positive → 1. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLQuoteElement
The interface shared by <blockquote>, <q>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
cite |
cite |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLScriptElement
The interface for <script>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
src |
src |
string |
Reflects verbatim — no base-URL resolution. |
type |
type |
string |
Reflects the content attribute verbatim. |
defer |
defer |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
async |
async |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
noModule |
nomodule |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
crossOrigin |
crossorigin |
nullable enum |
Keywords: anonymous · use-credentials. Missing attribute → null; any other present value → "anonymous"; assigning null removes the attribute. |
referrerPolicy |
referrerpolicy |
enum |
Keywords: "" · no-referrer · no-referrer-when-downgrade · same-origin · origin · strict-origin · origin-when-cross-origin · strict-origin-when-cross-origin · unsafe-url. Missing → ""; invalid → "". |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLSelectElement
The interface for <select>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
name |
name |
string |
Reflects the content attribute verbatim. |
required |
required |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
disabled |
disabled |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
multiple |
multiple |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLSlotElement
The interface for <slot>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
name |
name |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLSourceElement
The interface for <source>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
src |
src |
string |
Reflects verbatim — no base-URL resolution. |
type |
type |
string |
Reflects the content attribute verbatim. |
srcset |
srcset |
string |
Reflects the content attribute verbatim. |
sizes |
sizes |
string |
Reflects the content attribute verbatim. |
media |
media |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLSpanElement
The interface for <span>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLStyleElement
The interface for <style>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
media |
media |
string |
Reflects the content attribute verbatim. |
type |
type |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTableCaptionElement
The interface for <caption>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTableCellElement
The interface shared by <td>, <th>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
colSpan |
colspan |
number |
unset → 1; clamped to [1, 1000]. |
rowSpan |
rowspan |
number |
unset → 1; clamped to [0, 65534]. |
headers |
headers |
string |
Reflects the content attribute verbatim. |
scope |
scope |
enum |
Keywords: row · col · rowgroup · colgroup. Missing → ""; invalid → "". |
abbr |
abbr |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTableColElement
The interface shared by <col>, <colgroup>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
span |
span |
number |
unset → 1; clamped to [1, 1000]. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTableElement
The interface for <table>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTableRowElement
The interface for <tr>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTableSectionElement
The interface shared by <thead>, <tbody>, <tfoot>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTemplateElement
The interface for <template>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTextAreaElement
The interface for <textarea>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
name |
name |
string |
Reflects the content attribute verbatim. |
placeholder |
placeholder |
string |
Reflects the content attribute verbatim. |
required |
required |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
disabled |
disabled |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
readOnly |
readonly |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
rows |
rows |
number |
unset → 2; minimum 1 (an out-of-range value falls back to the default). |
cols |
cols |
number |
unset → 20; minimum 1 (an out-of-range value falls back to the default). |
wrap |
wrap |
enum |
Keywords: soft · hard. Missing → "soft"; invalid → "soft". |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTimeElement
The interface for <time>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
dateTime |
datetime |
string |
Reflects the content attribute verbatim. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTitleElement
The interface for <title>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLTrackElement
The interface for <track>. Extends HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
src |
src |
string |
Reflects verbatim — no base-URL resolution. |
kind |
kind |
enum |
Keywords: subtitles · captions · descriptions · chapters · metadata. Missing → "subtitles"; invalid → "metadata". |
srclang |
srclang |
string |
Reflects the content attribute verbatim. |
label |
label |
string |
Reflects the content attribute verbatim. |
default |
default |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLUListElement
The interface for <ul>. Extends HTMLElement → Element.
No interface-specific reflected properties — every member comes from HTMLElement and Element. Use getAttribute / setAttribute for any other attribute.
See also
- Element —
getAttribute/setAttribute, content, classList, traversal, insertion
- HTMLElement — the global reflected properties every HTML element inherits
- JavaScript DOM API — the interface hierarchy and
instanceof
HTMLVideoElement
The interface for <video>. Extends HTMLMediaElement → HTMLElement → Element.
Reflected properties
All setters are guarded and throw NoModificationAllowedError on a read-only document.
| Property |
Attribute |
Type |
Notes |
width |
width |
number |
unset → 0. |
height |
height |
number |
unset → 0. |
poster |
poster |
string |
Reflects the content attribute verbatim. |
playsInline |
playsinline |
boolean (presence) |
Reading reflects whether the attribute is present; writing false removes it, any other value sets it present. |
See also