Documentation
Installation #
Script tag (CDN) #
The simplest way. Add these two lines to your HTML:
<script src="https://unpkg.com/@digicreon/mujs@1.4.8/dist/mu.min.js"></script>
<script>mu.init();</script>
You can also use jsDelivr:
<script src="https://cdn.jsdelivr.net/npm/@digicreon/mujs@1.4.8/dist/mu.min.js"></script>
<script>mu.init();</script>
With Subresource Integrity (SRI):
<script src="https://unpkg.com/@digicreon/mujs@1.4.8/dist/mu.min.js"
integrity="sha384-x9kao8F430kRoLUGlLYGRC2FPo+rCsVlMUItQA1zbf0ZsIcht6wv8nikdx/Prqh2"
crossorigin="anonymous"></script>
<script>mu.init();</script>
<script src="https://cdn.jsdelivr.net/npm/@digicreon/mujs@1.4.8/dist/mu.min.js"
integrity="sha384-x9kao8F430kRoLUGlLYGRC2FPo+rCsVlMUItQA1zbf0ZsIcht6wv8nikdx/Prqh2"
crossorigin="anonymous"></script>
<script>mu.init();</script>
npm #
npm install @digicreon/mujs
Then import it in your JavaScript:
import mu from "@digicreon/mujs";
mu.init();
Quick start #
After including µJS and calling mu.init(), all internal links are automatically intercepted. Clicking a link fetches the page via AJAX and replaces the current <body> with the fetched <body>. The page title is updated automatically. Browser history (back/forward buttons) works as expected.
<!DOCTYPE html>
<html>
<head>
<title>My site</title>
<script src="https://unpkg.com/@digicreon/mujs/dist/mu.min.js"></script>
<script>mu.init();</script>
</head>
<body>
<!-- These links are automatically handled by µJS -->
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
<main id="content">
<p>Page content here.</p>
</main>
<!-- This link is NOT handled (external URL) -->
<a href="https://example.com">External link</a>
<!-- This link is NOT handled (explicitly disabled) -->
<a href="/file.pdf" mu-disabled>Download PDF</a>
</body>
</html>
By default, µJS replaces the entire <body>. To replace only a fragment of the page:
<a href="/about" mu-target="#content" mu-source="#content">About</a>
This fetches /about, extracts the #content element from the response, and replaces the current #content with it.
Link interception #
µJS automatically intercepts clicks on <a> links and navigates via AJAX instead of a full page reload. However, not all links are intercepted — µJS applies a set of rules to determine which links it should handle.
Which links are intercepted? #
µJS intercepts links that point to the same origin: absolute paths (/about), relative URLs (page.html, ../other/page.html), and absolute URLs on the same domain (https://mysite.com/about). If your page uses a <base> tag, relative URLs are resolved accordingly. Note that only the <base> tag from the initially loaded page is used; <base> tags in dynamically fetched pages are ignored.
Exclusion rules #
A link is not intercepted if any of the following conditions is true:
- The URL points to a different origin (e.g.
https://other-domain.com/...,//cdn.example.com/...) - The URL is a non-HTTP scheme (e.g.
mailto:,tel:,javascript:) - The URL is a hash-only link (e.g.
#section) - The link has a
targetattribute (e.g.target="_blank") - The link has a
downloadattribute - The link has a
mu-disabledattribute
Examples #
<!-- Intercepted (absolute path) -->
<a href="/about">About</a>
<!-- Intercepted (relative URL) -->
<a href="page.html">Page</a>
<a href="../other/page.html">Other page</a>
<!-- Intercepted (absolute same-origin URL) -->
<a href="https://mysite.com/about">About</a>
<!-- NOT intercepted (different origin) -->
<a href="https://github.com/Digicreon/mujs">GitHub</a>
<!-- NOT intercepted (protocol-relative, different origin) -->
<a href="//cdn.example.com/file.js">CDN link</a>
<!-- NOT intercepted (mailto) -->
<a href="mailto:hello@example.com">Email us</a>
<!-- NOT intercepted (hash-only) -->
<a href="#section">Jump to section</a>
<!-- NOT intercepted (target attribute) -->
<a href="/page" target="_blank">New tab</a>
<!-- NOT intercepted (download attribute) -->
<a href="/files/report.pdf" download>Download PDF</a>
<!-- NOT intercepted (explicitly disabled) -->
<a href="/legacy-page" mu-disabled>Legacy page</a>
The mu-disabled attribute is the recommended way to opt out a specific internal link from µJS interception. See Attributes reference for more details.
Server-side detection #
µJS adds HTTP headers to every request, allowing your server to distinguish AJAX navigations from regular page loads. The most common use case is returning a partial HTML fragment instead of the full page, saving bandwidth and server-side rendering time.
Request headers #
| Header | Value | Sent on |
|---|---|---|
X-Requested-With | XMLHttpRequest | All requests |
X-Mu-Mode | replace, append, patch, etc. | All requests |
X-Mu-Method | PUT, DELETE, etc. | Non-GET requests only |
X-Mu-Prefetch | 1 | Prefetch requests only |
The X-Requested-With header uses the standard XMLHttpRequest value, which is the de facto convention for identifying AJAX requests. Most server-side frameworks already provide a built-in helper to check for it (e.g. request.xhr? in Rails, request.is_xhr in Flask).
Example: returning a partial #
Instead of rendering the full page layout (header, nav, footer), you can return just the content fragment when the request comes from µJS:
// PHP
if ($_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') {
// µJS request — return only the fragment
echo $fragment;
} else {
// Normal request — return the full page
include 'layout.php';
}
This is entirely optional — µJS works perfectly with full-page responses (it extracts the relevant fragment using mu-source). But returning partials can reduce response size and server load.
If you're coming from htmx, X-Requested-With: XMLHttpRequest serves the same purpose as the HX-Request: true header.
Target & Source #
By default, µJS replaces the entire body. You can configure which part of the page is replaced (target) and which part of the response is extracted (source).
Global configuration #
mu.init({
target: "main", // CSS selector — element to replace on the page
source: "main" // CSS selector — element to extract from the response
});
Per-link override #
<a href="/page.html" mu-target="#content" mu-source="#content">Load</a>
The mu-target attribute sets the element to replace in the current page. The mu-source attribute sets the element to extract from the fetched page. Both accept CSS selectors.
If mu-source is not set, it falls back to the global source configuration, then to using the same selector as target.
Relative targets (&) #
The & character in a selector is replaced by the ID selector of the triggering element. If the element has no id, one is auto-generated (prefixed mu-). This is useful for reusable components — lists of items, cards, table rows — where generating unique IDs server-side would be cumbersome.
<!-- Button that updates itself -->
<button mu-url="/api/status" mu-target="&">Refresh</button>
<!-- Element that updates a child -->
<div mu-trigger="click" mu-mode="update"
mu-url="/api/list" mu-target="& > .list">
<div class="list">...</div>
</div>
<!-- Button that updates an adjacent element -->
<button mu-url="/api/count" mu-target="& + .result">Load</button>
<div class="result"></div>
The & syntax also works in mu-patch-target for patch responses:
<!-- Server response: target relative to the trigger -->
<div mu-patch-target="& > .list" mu-patch-mode="update">...</div>
Inspired by CSS nesting syntax, the & is valid HTML5 in attribute values (no need for & as it is not followed by a named entity).
Modes #
The mu-mode attribute controls how fetched content is injected into the page. Default: replace.
| Mode | Behavior |
|---|---|
replace | Replace the target node with the source node (default) |
update | Replace the inner content of the target with the source's inner content |
prepend | Insert the source node at the beginning of the target |
append | Insert the source node at the end of the target |
before | Insert the source node before the target |
after | Insert the source node after the target |
remove | Remove the target node (source is ignored) |
none | Do nothing to the DOM (events are still fired) |
patch | Process multiple targeted fragments (see Patch mode) |
Example #
<a href="/notifications"
mu-mode="update" mu-target="#notifs" mu-source="#notifs">
Refresh notifications
</a>
Patch mode #
Patch mode allows a single request to update multiple parts of the page. The server returns HTML fragments, each annotated with a target and an optional mode.
Link triggering a patch #
<a href="/api/comments/new" mu-mode="patch">Add comment</a>
Server response #
The server returns plain HTML. Each element with a mu-patch-target attribute is a patch fragment:
<!-- Replaces #comment-42 (default mode: replace) -->
<div class="comment" mu-patch-target="#comment-42">
Updated comment text
</div>
<!-- Appends a new comment to #comments -->
<div class="comment" mu-patch-target="#comments" mu-patch-mode="append">
New comment
</div>
<!-- Updates the page title -->
<title mu-patch-target="title">New page title</title>
<!-- Adds a stylesheet -->
<link rel="stylesheet" href="/css/gallery.css"
mu-patch-target="head" mu-patch-mode="append">
<!-- Removes an element -->
<div mu-patch-target="#old-banner" mu-patch-mode="remove"></div>
Patch fragments are standard HTML elements — no special tags needed. The mu-patch-* attributes are preserved on injected nodes for debugging.
The mu-patch-mode attribute accepts the same values as mu-mode (except patch and none). Default is replace.
Patch and browser history #
By default, patch mode does not modify browser history. To add the URL to history:
<a href="/products?cat=3" mu-mode="patch" mu-patch-history="true">Filter</a>
Forms #
µJS intercepts form submissions. HTML5 validation (reportValidity()) is checked before any request. When a form has multiple submit buttons with different name/value attributes, µJS includes the clicked button's data in the submission — matching standard browser behavior.
GET forms #
Data is serialized as a query string. Behaves like a link.
<form action="/search" method="get"
mu-target="#results" mu-source="#results">
<input type="text" name="q">
<button type="submit">Search</button>
</form>
POST forms #
Data is sent as FormData. History is disabled by default (POST responses should not be replayed via the browser back button).
<form action="/comment/create" method="post">
<textarea name="body"></textarea>
<button type="submit">Send</button>
</form>
PUT / PATCH / DELETE forms #
Use mu-method to override the HTTP method. The form data is sent as FormData, like POST.
<!-- PUT form -->
<form action="/api/user/1" mu-method="put">
<input type="text" name="name">
<button type="submit">Update</button>
</form>
<!-- DELETE form (no data needed) -->
<form action="/api/user/1" mu-method="delete">
<button type="submit">Delete</button>
</form>
POST form with patch response #
<div id="comments">
<p>First comment</p>
</div>
<form id="comment-form" action="/comment/create" method="post"
mu-mode="patch">
<textarea name="body"></textarea>
<button type="submit">Send</button>
</form>
Server response:
<div class="comment" mu-patch-target="#comments" mu-patch-mode="append">
<p>The new comment</p>
</div>
<form id="comment-form" action="/comment/create" method="post"
mu-patch-target="#comment-form"
mu-mode="patch">
<textarea name="body"></textarea>
<button type="submit">Send</button>
</form>
The new comment is appended to the list, and the form is replaced with a blank version.
Custom validation #
<form action="/save" method="post" mu-validate="myValidator">...</form>
<script>
function myValidator(form) {
return form.querySelector('#name').value.length > 0;
}
</script>
Quit-page confirmation #
Add mu-confirm-quit to a form. If any input is modified, the user is prompted before navigating away:
<form action="/save" method="post" mu-confirm-quit>
<input type="text" name="title">
<button type="submit">Save</button>
</form>
HTTP methods #
By default, links use GET and forms use their method attribute. The mu-method attribute overrides the HTTP method for any element.
Supported values: get, post, put, patch, delete, sse.
<!-- DELETE button -->
<button mu-url="/api/item/42" mu-method="delete"
mu-mode="remove" mu-target="#item-42">
Delete
</button>
<!-- PUT link -->
<a href="/api/publish/5" mu-method="put" mu-mode="none">Publish</a>
Non-GET requests send an X-Mu-Method header with the HTTP method. See Server-side detection for the full list of headers sent by µJS.
Non-GET clicks (via mu-method) do not use the prefetch cache and default to mu-history="false". This can be overridden with mu-history="true" if needed.
Triggers #
µJS supports custom event triggers via the mu-trigger attribute. This allows any element with a mu-url to initiate a fetch on events other than click or submit.
Default triggers #
When mu-trigger is absent, the trigger depends on the element type:
| Element | Default trigger |
|---|---|
<a> | click |
<form> | submit |
<input>, <textarea>, <select> | change |
| Any other element | click |
Available triggers #
| Trigger | Browser event(s) | Typical elements |
|---|---|---|
click | click | Any element (default for <a>, <button>, <div>...) |
submit | submit | <form> |
change | input | <input>, <textarea>, <select> |
blur | change + blur (deduplicated) | <input>, <textarea>, <select> |
focus | focus | <input>, <textarea>, <select> |
load | (fires immediately when rendered) | Any element |
Examples #
Live search with debounce:
<input type="text" name="q"
mu-trigger="change" mu-debounce="500"
mu-url="/search" mu-target="#results" mu-source="#results"
mu-mode="update">
Action on focus (e.g. load suggestions):
<input type="text" mu-trigger="focus"
mu-url="/suggestions" mu-target="#suggestions" mu-mode="update">
Action on blur (save on field exit):
<input type="text" name="title" mu-trigger="blur"
mu-url="/api/save" mu-method="put" mu-target="#status" mu-mode="update">
Load content immediately:
<div mu-trigger="load"
mu-url="/sidebar" mu-target="#sidebar" mu-mode="update">
</div>
Polling #
Combine mu-trigger="load" with mu-repeat to poll a URL at regular intervals:
<div mu-trigger="load" mu-repeat="5000"
mu-url="/notifications" mu-target="#notifs" mu-mode="update">
</div>
The first fetch fires immediately, then every 5 seconds. Polling intervals are automatically cleaned up when the element is removed from the DOM.
Debounce #
Use mu-debounce to delay the fetch until the user stops interacting:
<input type="text" name="q" mu-debounce="300"
mu-url="/search" mu-target="#results" mu-mode="update">
Note: Triggers other than click and submit default to no browser history entry and no scroll (mu-history="false", mu-scroll="false").
Server-Sent Events (SSE) #
µJS supports real-time updates via Server-Sent Events. Set mu-method="sse" to open an EventSource connection instead of a one-shot fetch.
<div mu-trigger="load" mu-url="/chat/stream"
mu-mode="patch" mu-method="sse">
</div>
Each incoming SSE message is treated as HTML and rendered according to the element's mu-mode. In patch mode, the server sends HTML fragments with mu-patch-target attributes, just like a regular patch response.
Server-side example #
event: message
data: <div mu-patch-target="#messages" mu-patch-mode="append"><p>New message!</p></div>
event: message
data: <span mu-patch-target="#online-count">42</span>
Limitations #
- No custom headers:
EventSourcedoes not support custom HTTP headers. Use query parameters for authentication (e.g.mu-url="/stream?token=abc"). - Connection limit: Browsers allow ~6 SSE connections per domain in HTTP/1.1. Use HTTP/2 to avoid this limit.
- Automatic cleanup: SSE connections are closed when the element is removed from the DOM (e.g. when the page changes).
History & Scroll #
mu-history controls whether the URL is added to browser history. mu-scroll controls whether the page scrolls to top after rendering. Both attributes are independent.
<!-- Skip history on a link -->
<a href="/panel" mu-history="false">Open panel</a>
<!-- Skip history globally -->
<script>mu.init({ history: false });</script>
<!-- Scroll to top without adding history -->
<a href="/page" mu-history="false" mu-scroll="true">Link</a>
Defaults #
Defaults for mu-history and mu-scroll depend on the mode and context:
| Mode | Context | mu-history |
mu-scroll |
|---|---|---|---|
replace, update | Links (GET) | true | true |
replace, update | Links (POST/PUT/PATCH/DELETE via mu-method) | false | true |
replace, update | Forms (GET) | true | true |
replace, update | Forms (POST/PUT/PATCH/DELETE) | false | true |
replace, update | Triggers (change, blur, focus, load) | false | false |
replace, update | SSE | false | false |
append, prepend, before, after, remove, none | Any | false | false |
patch | Any | false | false |
Redirections always add the URL to browser history, regardless of the mu-history setting. In patch mode, use mu-patch-history="true" to add the URL to history.
Scroll restoration #
When the user navigates with the browser's back/forward buttons, µJS automatically restores the scroll position to where it was before leaving the page. This works out of the box — no configuration needed.
Prefetch #
µJS prefetches pages when the user hovers over a link. This saves ~100–300ms on click, making navigation feel nearly instant.
Default behavior #
Prefetch is enabled by default for GET requests. When the user hovers over a link, µJS waits 50ms before fetching the target page in the background — this avoids unnecessary requests when the mouse passes briefly over a link. The result is cached (one entry per URL), and the cache is consumed on click. Links with a non-GET mu-method are excluded from prefetch.
The cache lifetime defaults to 3 seconds. You can adjust it via the prefetchTtl option (in milliseconds):
mu.init({ prefetchTtl: 5000 }); // 5 seconds
Disable globally #
mu.init({ prefetch: false });
Disable per-link #
<a href="/page.html" mu-prefetch="false">No prefetch</a>
DOM morphing #
DOM morphing updates the existing DOM to match the new content instead of replacing it entirely. This preserves focus, input values, scroll positions, CSS transitions, and video playback state.
Installation #
Idiomorph is an optional external library. Load it before µJS so that µJS detects it automatically:
<script src="https://cdn.jsdelivr.net/npm/idiomorph@0.7.4/dist/idiomorph.min.js"></script>
<script src="https://unpkg.com/@digicreon/mujs/dist/mu.min.js"></script>
<script>mu.init();</script>
How it works #
When idiomorph is available on the page, µJS uses it for morphing automatically. No configuration needed.
Enable/disable globally #
mu.init({ morph: false });
Enable/disable per-link #
<a href="/page.html" mu-morph="false">No morphing</a>
Custom morph function #
mu.setMorph(function(target, html, opts) {
myMorphLib.morph(target, html, opts);
});
View Transitions #
µJS supports the browser View Transitions API. When the browser supports it, page transitions are animated smoothly.
Default #
View Transitions are enabled by default when the browser supports them.
Disable globally #
mu.init({ transition: false });
Disable per-link #
<a href="/page.html" mu-transition="false">No transition</a>
Progress bar #
µJS displays a thin progress bar at the top of the page during AJAX requests. It provides visual feedback that content is loading.
Default #
The progress bar is enabled by default.
Disable #
mu.init({ progress: false });
Custom styling #
The progress bar has the id #mu-progress. Since µJS applies inline styles for positioning and animation, use !important to override them:
#mu-progress {
background: red !important;
height: 5px !important;
top: auto !important;
bottom: 0 !important;
}
Custom loading indicator #
For more advanced customization (e.g. a full-screen overlay with a spinner), disable the built-in progress bar and use events to show and hide your own indicator:
mu.init({ progress: false });
document.addEventListener("mu:before-fetch", function() {
document.getElementById("loading-overlay").style.display = "flex";
});
document.addEventListener("mu:after-render", function() {
document.getElementById("loading-overlay").style.display = "none";
});
document.addEventListener("mu:fetch-error", function() {
document.getElementById("loading-overlay").style.display = "none";
});
Scripts #
When µJS loads a page via AJAX, it automatically processes <script> tags found in the fetched content.
Execution rules #
| Script type | Behavior |
|---|---|
Inline (<script>...</script>) | Re-executed on every navigation |
External (<script src="...">) | Executed only once — skipped on subsequent navigations if the same src was already loaded |
µJS tracks external scripts by their src URL. On the initial page load, all existing <script src="..."> are registered. When a fetched page includes an external script with the same src, it is not loaded again. This prevents libraries like jQuery or analytics scripts from being re-initialized on every page change.
New <link>, <style>, and <script> elements found in the fetched <head> are also merged into the current page's <head>, following the same deduplication rules.
Preventing script execution #
Add mu-disabled to a <script> tag to prevent µJS from executing it during AJAX navigation:
<script mu-disabled>
// This script runs on initial page load (full page),
// but NOT when loaded via µJS navigation.
thirdPartyWidget.init();
</script>
This is useful for scripts that should only run once on a full page load (analytics snippets, third-party widgets) and must not be re-executed when the page content is fetched via µJS.
Events #
µJS dispatches CustomEvent events on document. All events carry a detail object with lastUrl and previousUrl.
| Event | Cancelable | Description |
|---|---|---|
mu:init |
No | Fired after initialization |
mu:before-fetch |
Yes | Fired before fetching. preventDefault() aborts the load. |
mu:before-render |
Yes | Fired after fetch, before DOM injection. detail.html can be modified. |
mu:after-render |
No | Fired after DOM injection |
mu:fetch-error |
No | Fired on fetch failure or HTTP error |
Run code after each page load #
document.addEventListener("mu:after-render", function(e) {
console.log("Loaded: " + e.detail.url);
myApp.initWidgets();
});
Cancel a navigation #
document.addEventListener("mu:before-fetch", function(e) {
if (e.detail.url === "/restricted") {
e.preventDefault();
}
});
Modify HTML before rendering #
document.addEventListener("mu:before-render", function(e) {
e.detail.html = e.detail.html.replace("foo", "bar");
});
Handle errors #
document.addEventListener("mu:fetch-error", function(e) {
if (e.detail.status === 404) {
alert("Page not found");
}
});
Attributes reference #
All attributes support both mu-* and data-mu-* syntax.
| Attribute | Description |
|---|---|
mu-disabled | Disable µJS on this element. On links and forms, prevents interception. On <script>, prevents execution during AJAX navigation (see Scripts). |
mu-mode | Injection mode (replace, update, prepend, append, before, after, remove, none, patch). |
mu-target | CSS selector for the target node in the current page. Use & for relative targets. |
mu-source | CSS selector for the source node in the fetched page. |
mu-url | Override the URL to fetch (instead of href / action). |
mu-prefix | URL prefix for the fetch request. |
mu-title | Selector for the title node. Supports selector/attribute syntax. Empty string to disable. |
mu-history | Add URL to browser history (true/false). Default depends on mode and context. |
mu-scroll | Force (true) or prevent (false) scrolling to top. Default depends on mode and context. |
mu-morph | Disable morphing on this element (false). |
mu-transition | Disable view transitions on this element (false). |
mu-prefetch | Disable prefetch on hover for this link (false). |
mu-method | HTTP method: get, post, put, patch, delete, or sse. |
mu-trigger | Event trigger: click, submit, change, blur, focus, load. |
mu-debounce | Debounce delay in milliseconds (e.g. "500"). |
mu-repeat | Polling interval in milliseconds (e.g. "5000"). |
mu-confirm | Show a confirmation dialog before loading. |
mu-confirm-quit | (Forms) Prompt before leaving if the form has been modified. |
mu-validate | (Forms) Name of a JS validation function. Must return true/false. |
mu-patch-target | (Patch fragments) CSS selector of the target node. Use & for relative targets. |
mu-patch-mode | (Patch fragments) Injection mode for this fragment. |
mu-patch-history | Set to true to add the URL to browser history in patch mode. Default: false. |
Configuration reference #
Options passed to mu.init():
| Option | Type | Default | Description |
|---|---|---|---|
processLinks | boolean | true | Intercept link clicks |
processForms | boolean | true | Intercept form submissions |
target | string | "body" | CSS selector for the default replacement target |
source | string | "body" | CSS selector for the default content source |
title | string | "title" | CSS selector for the page title element |
mode | string | "replace" | Default injection mode |
history | boolean | true | Add URL to browser history |
scroll | boolean|null | null | Scroll behavior. null = auto (depends on mode and context). |
urlPrefix | string | "" | Prefix added to all fetch URLs |
prefetch | boolean | true | Enable hover prefetch |
prefetchTtl | number | 3000 | Prefetch cache TTL in milliseconds |
morph | boolean | true | Enable DOM morphing (when idiomorph is available) |
transition | boolean | true | Enable View Transitions API |
progress | boolean | true | Show progress bar during loading |
confirmQuitText | string | "Are you | Quit-page confirmation message |
Programmatic API #
mu.init(config) #
Initialize µJS with optional configuration. Must be called before any navigation occurs. See Configuration reference above for the list of available options.
mu.init({
target: "main",
source: "main",
prefetch: true
});
mu.load(url, config) #
Programmatically navigate to a URL. Accepts the same options as mu.init() for per-request overrides.
mu.load("/dashboard.html");
// With overrides
mu.load("/fragment.html", {
target: "#sidebar",
source: "#sidebar-content",
history: false
});
mu.getLastUrl() #
Returns the URL of the most recent µJS navigation.
var lastUrl = mu.getLastUrl();
mu.getPreviousUrl() #
Returns the URL of the navigation before the current one.
var prevUrl = mu.getPreviousUrl();
mu.setConfirmQuit(enabled) #
Programmatically enable or disable the confirm-quit prompt.
// Enable after user makes changes
mu.setConfirmQuit(true);
// Disable after saving
mu.setConfirmQuit(false);
mu.setMorph(fn) #
Register a custom morph function. The function receives the target element, the new HTML, and an options object.
mu.setMorph(function(target, html, opts) {
myMorphLib.morph(target, html, opts);
});
Browser support #
µJS works in all modern browsers. The minimum versions are determined by AbortController (used for request cancellation).
Desktop #
| Browser | Version | Release date |
|---|---|---|
| Chrome | 66+ | April 2018 |
| Edge | 79+ | January 2020 |
| Firefox | 57+ | November 2017 |
| Safari | 12.1+ | March 2019 |
| Opera | 53+ | May 2018 |
Mobile #
| Browser | Version | Release date |
|---|---|---|
| Chrome Android | 66+ | April 2018 |
| Safari iOS | 11.3+ | March 2018 |
| Firefox Android | 57+ | November 2017 |
| Opera Mobile | 47+ | May 2018 |
View Transitions require Chrome/Edge 111+. On unsupported browsers, transitions are skipped silently.
DOM morphing requires a separate library (idiomorph recommended). Without it, µJS falls back to direct DOM replacement.
µJS does not support Internet Explorer or legacy Edge (EdgeHTML).