JavaScript
Pagelove Primitives Library
The Pagelove Primitives library provides a DOM-aware HTTP client runtime for Pagelove applications.
It allows browser code to:
- Address elements using stable CSS selectors
- Issue HTTP methods (
OPTIONS,PUT,POST,DELETE) directly against DOM nodes - Discover server-declared capabilities
- Mutate documents using standard HTTP semantics
- Remain framework-free
This library is intentionally small and infrastructure-oriented.
Usage
<script type="module">
import { PLDocument } from "https://cdn.pagelove.net/js/pagelove-primitives/1a5a161/index.mjs";
</script>
(Replace with the pinned CDN version as required.)
Core concepts
Documents
A PLDocument represents a Pagelove resource URL and its DOM.
const doc = new PLDocument();
By default, this binds to window.location.href and the active document.
Elements
A PLElement represents a single DOM node bound to a document URL.
Each element:
- Has a stable CSS selector
- Can issue HTTP requests scoped to itself
- Mirrors server authorization via runtime methods
You do not normally construct these manually.
They are created automatically during capability discovery.
Capability discovery (OPTIONS)
Pagelove uses HTTP OPTIONS to advertise element-level capabilities.
await doc.OPTIONS();
This performs:
- An
OPTIONSrequest with:Accept: multipart/mixedPrefer: return=representation
- Parses the multipart response
- Subscribes to selectors declared in
Content-Rangeheaders - Emits
PLCapabilityevents when matching nodes appear
When a capability is discovered, methods are dynamically attached to DOM nodes.
Example:
element.PUT(...)
element.POST(...)
element.DELETE(...)
Only methods explicitly authorized by the server are exposed.
Example: enabling element methods
const doc = new PLDocument();
await doc.OPTIONS();
// Later, in the DOM:
const article = document.querySelector("article");
// If authorized:
await article.PUT();
await article.DELETE();
No methods exist until the server advertises them.
Element selectors
Each PLElement exposes a stable selector:
element.selector
Selector generation strategy:
- Uses element
idif present - Otherwise builds a path using
:nth-child(...) - Anchors to nearest parent with an
id - Falls back to tag name
Selectors are deterministic and server-resolvable.
They are transmitted using:
Range: selector=<css selector>
HTTP methods
PUT
Replace the element.
await element.PUT();
Or:
await element.PUT("<div>New HTML</div>");
Defaults to element.outerHTML if no body is supplied.
POST
Append a new child node returned by the server.
await element.POST("<li>New item</li>");
If successful:
- Response body is parsed as HTML
- A single node is appended to the element
DELETE
Remove the element.
await element.DELETE();
On success:
- Server deletes the element
- Client removes it from the DOM
Events
PLCapability
Emitted when server capabilities are discovered.
document.addEventListener("PLCapability", event => {
console.log(event.detail.selector);
console.log(event.detail.allow);
});
Payload:
{
selector: "<css selector>",
allow: ["GET", "PUT", "POST", "DELETE"]
}
Bubbles and is composed.
PLMethodCompleted
Emitted after any method request completes.
document.addEventListener("PLMethodCompleted", event => {
console.log(event.detail.method);
console.log(event.detail.response.status);
});
Multipart support
Capability discovery relies on multipart HTTP responses.
The library provides:
MultipartMessageMultipartBody
These parse:
Content-Type: multipart/mixed; boundary=...
Each part may contain:
Content-Range: selector=<css>Allow: PUT, POST, DELETE
This mechanism allows servers to advertise fine-grained DOM permissions.
Server contract
The primitives assume:
- Selector-based
Rangeheaders - Multipart
OPTIONSresponses - Per-element authorization
- HTML fragments returned by
POST
This mirrors Pagelove’s document-centric protocol model.
Minimal usage example
import { PLDocument } from "https://cdn.pagelove.net/js/primitives/latest/index.mjs";
const doc = new PLDocument();
await doc.OPTIONS();
document.addEventListener("click", async e => {
if (e.target.matches(".delete-button")) {
await e.target.closest("article").DELETE();
}
});
Summary
Pagelove Primitives provide:
- DOM-addressable HTTP operations
- Selector-scoped resource mutation
- Server-declared capability enforcement
- Multipart-based permission discovery
- Zero framework dependencies
They are the client-side counterpart to Pagelove’s document-native server model: the DOM is the API.