|
|
||
|---|---|---|
| src | init push | |
| LICENSE | Initial commit | |
| README.md | init push | |
FX: Bare Metal AJAX Library
~1.27KB (Minified) | No Dependencies | Zero-Regex Parser | High Performance
FX is a hyper-efficient, declarative AJAX library. It uses a single attribute (fx) with a heuristic parser to determine behavior. It is designed for speed, low memory usage, and zero DOM thrashing.
Installation
There is no build step. Just include this script in of your <head>.
It must be used with defer.
<script src="fx.js" defer></script>
The Syntax
Usage relies on a single attribute: fx="...". The value is a space-separated string. The parser scans tokens to detect configuration. Order does not matter.
Parser Rules
The library uses strict native string comparison (no Regex) for performance. You must follow these rules exactly:
| Config | Identifier Rule | Valid Values | Default |
|---|---|---|---|
| Method | Exact uppercase Match | GET, POST, PUT, DELETE, PATCH |
GET |
| Trigger | Starts with @ |
@click, @change, @submit, @mouseenter, etc... |
Inference* |
| Target | Starts with specific char | #id, .class, [attr], body, this |
this |
| Swap | Exact whitelist Match | outerHTML, innerHTML, beforebegin, afterbegin, beforeend, afterend, none |
outerHTML |
| URL | Anything else | /api/path |
Required |
*Inference: Forms default to submit, Inputs to change, Buttons/Links to click. |
Examples
1. Basic Link
Performs a GET request and replaces the button itself (outerHTML) with the response.
<button fx="/get-time">Load Time</button>
2. Form Submission
Performs a POST request. The response replaces the content of #results.
<form fx="POST /save-user #results innerHTML">
<input name="username" />
<button>Save</button>
</form>
3. Search as you type
Triggers on keyup. Uses this to target the input itself (or use a selector for a results box).
<input name="q"
fx="/search @keyup #search-results innerHTML"
placeholder="Search..." />
<div id="search-results"></div>
4. Delete with Confirmation
You can combine standard JS confirm() via the lifecycle events (see below) or handle it on the server.
<button fx="DELETE /items/1 @click #item-1 outerHTML">Delete Item</button>
Request Behavior
- Headers: Automatically sends
FX-Request: true. - FormData: * If triggered inside a
<form>, it serializes the form.- If triggered on an input with a
name(outside a form), sends that single value.
- If triggered on an input with a
- Methods: *
GETandDELETErequests convert the FormData into URL Query Parameters automatically.POST,PUT,PATCHsend the FormData as the request body.
Lifecycle Events
FX emits standard CustomEvents. You can listen to them to extend functionality.
| Event Name | evt.detail |
Description |
|---|---|---|
fx:init |
() |
Fired when the element is first parsed and initialized. |
fx:config |
{cfg.requests} |
Cancelable. Fired before request setup. Good for adding headers or validation. |
fx:before |
{cfg} |
Cancelable. Fired immediately before fetch. Good for loading spinners. |
fx:after |
{cfg} |
Cancelable. Fired after response is received (text is ready). |
fx:swapped |
{cfg} |
Fired after the DOM has been updated. |
fx:error |
{cfg, error} |
Fired if the network request fails or returns non-200. |
fx:finally |
{cfg} |
Fired at the very end of the cycle (success or fail). |
Example: Adding a Loading Spinner
document.addEventListener("fx:before", (e) => {
e.target.classList.add("is-loading");
});
document.addEventListener("fx:finally", (e) => {
e.target.classList.remove("is-loading");
});
Example: Confirm Dialog
document.addEventListener("fx:config", (e) => {
// If the element has data-confirm, pause for user input
if (e.target.dataset.confirm) {
// We hook a confirm function into the config object
e.detail.cfg.confirm = async () => confirm(e.target.dataset.confirm);
}
});
View Transitions
If the browser supports the View Transitions API, FX automatically wraps the swap in document.startViewTransition. This allows for smooth CSS animations between states without extra JS.
Ignoring Elements
To prevent FX from initializing elements in a specific area (e.g., a third-party widget), add the fx-ignore attribute to a container.
<div fx-ignore>
<button fx="/submit">Nothing happens</button>
</div>