@digicreon/mujs 1.2.1 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -32
- package/dist/mu.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ No build step required. No dependencies. No framework. Just a single `<script>`
|
|
|
9
9
|
Inspired by [pjax](https://github.com/defunkt/jquery-pjax), [Turbo](https://turbo.hotwired.dev/) and [HTMX](https://htmx.org/), µJS aims to be simpler and lighter while covering the most common use cases.
|
|
10
10
|
|
|
11
11
|
- 🚀 **Fast** — Prefetch on hover, no full page reload, progress bar
|
|
12
|
-
- 🪶 **Lightweight** — Single file, ~
|
|
12
|
+
- 🪶 **Lightweight** — Single file, ~5 KB gzipped, zero dependencies
|
|
13
13
|
- 🔌 **Drop-in** — Works with any backend (PHP, Python, Ruby, Go…), no server-side changes needed
|
|
14
14
|
- 🧩 **Patch mode** — Update multiple page fragments in a single request
|
|
15
15
|
- 🎯 **Triggers** — Any element, any event: live search, polling, focus actions
|
|
@@ -28,11 +28,12 @@ Inspired by [pjax](https://github.com/defunkt/jquery-pjax), [Turbo](https://turb
|
|
|
28
28
|
- [HTTP methods](#http-methods)
|
|
29
29
|
- [Triggers](#triggers)
|
|
30
30
|
- [Server-Sent Events (SSE)](#server-sent-events-sse)
|
|
31
|
-
- [
|
|
31
|
+
- [History & Scroll](#history--scroll)
|
|
32
32
|
- [Scroll restoration](#scroll-restoration)
|
|
33
33
|
- [Prefetch](#prefetch)
|
|
34
34
|
- [DOM morphing](#dom-morphing)
|
|
35
35
|
- [View Transitions](#view-transitions)
|
|
36
|
+
- [Scripts](#scripts)
|
|
36
37
|
- [Progress bar](#progress-bar)
|
|
37
38
|
- [Events](#events)
|
|
38
39
|
- [Attributes reference](#attributes-reference)
|
|
@@ -100,8 +101,14 @@ After calling `mu.init()`, all internal links (URLs starting with `/`) are autom
|
|
|
100
101
|
<!-- This link is NOT handled (external URL) -->
|
|
101
102
|
<a href="https://example.com">External link</a>
|
|
102
103
|
|
|
104
|
+
<!-- This link is NOT handled (has target attribute) -->
|
|
105
|
+
<a href="/page" target="_blank">Opens in new tab</a>
|
|
106
|
+
|
|
107
|
+
<!-- This link is NOT handled (has download attribute) -->
|
|
108
|
+
<a href="/file.pdf" download>Download PDF</a>
|
|
109
|
+
|
|
103
110
|
<!-- This link is NOT handled (explicitly disabled) -->
|
|
104
|
-
<a href="/
|
|
111
|
+
<a href="/page" mu-disabled>Disabled link</a>
|
|
105
112
|
|
|
106
113
|
<script src="/path/to/mu.min.js"></script>
|
|
107
114
|
<script>mu.init();</script>
|
|
@@ -188,7 +195,7 @@ The `mu-patch-mode` attribute accepts the same values as `mu-mode` (except `patc
|
|
|
188
195
|
By default, patch mode does not modify browser history. To add the URL to history:
|
|
189
196
|
|
|
190
197
|
```html
|
|
191
|
-
<a href="/products?cat=3" mu-mode="patch" mu-patch-
|
|
198
|
+
<a href="/products?cat=3" mu-mode="patch" mu-patch-history="true">Filter</a>
|
|
192
199
|
```
|
|
193
200
|
|
|
194
201
|
|
|
@@ -209,7 +216,7 @@ Data is serialized as a query string. Behaves like a link.
|
|
|
209
216
|
|
|
210
217
|
### POST forms
|
|
211
218
|
|
|
212
|
-
Data is sent as `FormData`.
|
|
219
|
+
Data is sent as `FormData`. History is disabled by default (POST responses should not be replayed via the browser back button).
|
|
213
220
|
|
|
214
221
|
```html
|
|
215
222
|
<form action="/comment/create" method="post">
|
|
@@ -300,8 +307,6 @@ Supported values: `get`, `post`, `put`, `patch`, `delete`, `sse`.
|
|
|
300
307
|
|
|
301
308
|
Non-GET requests send an `X-Mu-Method` header with the HTTP method, allowing the server to distinguish between standard and µJS-initiated requests.
|
|
302
309
|
|
|
303
|
-
> **Note:** `mu-post` is deprecated. Use `mu-method="post"` instead.
|
|
304
|
-
|
|
305
310
|
|
|
306
311
|
## Triggers
|
|
307
312
|
|
|
@@ -383,7 +388,7 @@ Use `mu-debounce` to delay the fetch until the user stops interacting:
|
|
|
383
388
|
mu-url="/search" mu-target="#results" mu-mode="update">
|
|
384
389
|
```
|
|
385
390
|
|
|
386
|
-
> **Note:** Triggers other than `click` and `submit` default to
|
|
391
|
+
> **Note:** Triggers other than `click` and `submit` default to no browser history entry and no scroll (`mu-history="false"`, `mu-scroll="false"`).
|
|
387
392
|
|
|
388
393
|
|
|
389
394
|
## Server-Sent Events (SSE)
|
|
@@ -415,19 +420,34 @@ data: <span mu-patch-target="#online-count">42</span>
|
|
|
415
420
|
- **Automatic cleanup**: SSE connections are closed when the element is removed from the DOM (e.g. when the page changes).
|
|
416
421
|
|
|
417
422
|
|
|
418
|
-
##
|
|
423
|
+
## History & Scroll
|
|
419
424
|
|
|
420
|
-
|
|
425
|
+
`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.
|
|
421
426
|
|
|
422
427
|
```html
|
|
423
|
-
<!--
|
|
424
|
-
<a href="/panel" mu-
|
|
428
|
+
<!-- Skip history on a link -->
|
|
429
|
+
<a href="/panel" mu-history="false">Open panel</a>
|
|
430
|
+
|
|
431
|
+
<!-- Skip history globally -->
|
|
432
|
+
<script>mu.init({ history: false });</script>
|
|
425
433
|
|
|
426
|
-
<!--
|
|
427
|
-
<
|
|
434
|
+
<!-- Scroll to top without adding history -->
|
|
435
|
+
<a href="/page" mu-history="false" mu-scroll="true">Link</a>
|
|
428
436
|
```
|
|
429
437
|
|
|
430
|
-
|
|
438
|
+
Defaults for `mu-history` and `mu-scroll` depend on the mode and context:
|
|
439
|
+
|
|
440
|
+
| Mode | Context | `mu-history` | `mu-scroll` |
|
|
441
|
+
|---|---|---|---|
|
|
442
|
+
| `replace`, `update` | Links (GET) | `true` | `true` |
|
|
443
|
+
| `replace`, `update` | Forms (GET) | `true` | `true` |
|
|
444
|
+
| `replace`, `update` | Forms (POST/PUT/PATCH/DELETE) | `false` | `true` |
|
|
445
|
+
| `replace`, `update` | Triggers (change, blur, focus, load) | `false` | `false` |
|
|
446
|
+
| `replace`, `update` | SSE | `false` | `false` |
|
|
447
|
+
| `append`, `prepend`, `before`, `after`, `remove`, `none` | Any | `false` | `false` |
|
|
448
|
+
| `patch` | Any | `false` | `false` |
|
|
449
|
+
|
|
450
|
+
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.
|
|
431
451
|
|
|
432
452
|
|
|
433
453
|
## Scroll restoration
|
|
@@ -437,9 +457,9 @@ When the user navigates with the browser's back/forward buttons, µJS automatica
|
|
|
437
457
|
|
|
438
458
|
## Prefetch
|
|
439
459
|
|
|
440
|
-
When enabled (default), µJS fetches the target page when the user hovers over a link, before they click. This saves ~100-300ms of perceived loading time.
|
|
460
|
+
When enabled (default), µJS fetches the target page when the user hovers over a link, before they click. A 50ms delay filters accidental hover-throughs (mouse passing over a link without intent to click). This saves ~100-300ms of perceived loading time.
|
|
441
461
|
|
|
442
|
-
The prefetch cache stores one entry per URL and is consumed on click.
|
|
462
|
+
The prefetch cache stores one entry per URL and is consumed on click. Prefetch only applies to GET requests — elements with `mu-method="post"`, `put`, `patch`, `delete` or `sse` are never prefetched.
|
|
443
463
|
|
|
444
464
|
```html
|
|
445
465
|
<!-- Disable prefetch on a specific link -->
|
|
@@ -499,6 +519,33 @@ Enabled by default. Falls back silently on unsupported browsers.
|
|
|
499
519
|
```
|
|
500
520
|
|
|
501
521
|
|
|
522
|
+
## Scripts
|
|
523
|
+
|
|
524
|
+
When µJS loads a page, scripts are handled differently depending on their location:
|
|
525
|
+
|
|
526
|
+
- **`<head>` scripts** are merged additively. If a script (identified by its `src` or content) is already present in the current `<head>`, it is not re-added or re-executed. New scripts found in the fetched page's `<head>` are added and executed once.
|
|
527
|
+
- **`<body>` scripts** found in the injected content are re-executed on each navigation. External scripts (with `src`) are loaded only once — subsequent navigations skip them. Inline scripts are re-executed every time.
|
|
528
|
+
|
|
529
|
+
This means third-party scripts loaded in the `<head>` (analytics, tracking, widgets) are **not** re-executed by µJS. For example, a Plausible or Google Analytics script in the `<head>` will detect SPA navigations on its own via `pushState` interception — no special configuration is needed.
|
|
530
|
+
|
|
531
|
+
To prevent a `<body>` inline script from being re-executed on navigation, add `mu-disabled`:
|
|
532
|
+
|
|
533
|
+
```html
|
|
534
|
+
<script mu-disabled>
|
|
535
|
+
// This script runs only on the initial page load
|
|
536
|
+
oneTimeSetup();
|
|
537
|
+
</script>
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
For code that should run after every µJS navigation, use the `mu:after-render` event instead of inline scripts:
|
|
541
|
+
|
|
542
|
+
```javascript
|
|
543
|
+
document.addEventListener("mu:after-render", function(e) {
|
|
544
|
+
myApp.initWidgets();
|
|
545
|
+
});
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
|
|
502
549
|
## Progress bar
|
|
503
550
|
|
|
504
551
|
A thin progress bar (3px, blue) is displayed at the top of the page during fetch requests. It requires no external stylesheet.
|
|
@@ -582,9 +629,8 @@ All attributes support both `mu-*` and `data-mu-*` syntax.
|
|
|
582
629
|
| `mu-url` | Override the URL to fetch (instead of `href` / `action`). |
|
|
583
630
|
| `mu-prefix` | URL prefix for the fetch request. |
|
|
584
631
|
| `mu-title` | Selector for the title node. Supports `selector/attribute` syntax. Empty string to disable. |
|
|
585
|
-
| `mu-
|
|
586
|
-
| `mu-
|
|
587
|
-
| `mu-scroll-to-top` | Force (`true`) or prevent (`false`) scrolling to top. |
|
|
632
|
+
| `mu-history` | Add URL to browser history (`true`/`false`). Default depends on mode and context. |
|
|
633
|
+
| `mu-scroll` | Force (`true`) or prevent (`false`) scrolling to top. Default depends on mode and context. |
|
|
588
634
|
| `mu-morph` | Disable morphing on this element (`false`). |
|
|
589
635
|
| `mu-transition` | Disable view transitions on this element (`false`). |
|
|
590
636
|
| `mu-prefetch` | Disable prefetch on hover for this link (`false`). |
|
|
@@ -592,13 +638,12 @@ All attributes support both `mu-*` and `data-mu-*` syntax.
|
|
|
592
638
|
| `mu-trigger` | Event trigger: `click`, `submit`, `change`, `blur`, `focus`, `load`. |
|
|
593
639
|
| `mu-debounce` | Debounce delay in milliseconds (e.g. `"500"`). |
|
|
594
640
|
| `mu-repeat` | Polling interval in milliseconds (e.g. `"5000"`). |
|
|
595
|
-
| `mu-post` | *(Deprecated)* Use `mu-method="post"` instead. |
|
|
596
641
|
| `mu-confirm` | Show a confirmation dialog before loading. |
|
|
597
642
|
| `mu-confirm-quit` | *(Forms)* Prompt before leaving if the form has been modified. |
|
|
598
643
|
| `mu-validate` | *(Forms)* Name of a JS validation function. Must return `true`/`false`. |
|
|
599
644
|
| `mu-patch-target` | *(Patch fragments)* CSS selector of the target node. |
|
|
600
645
|
| `mu-patch-mode` | *(Patch fragments)* Injection mode for this fragment. |
|
|
601
|
-
| `mu-patch-
|
|
646
|
+
| `mu-patch-history` | Set to `true` to add the URL to browser history in patch mode. Default: `false`. |
|
|
602
647
|
|
|
603
648
|
|
|
604
649
|
## Configuration reference
|
|
@@ -607,7 +652,7 @@ Pass an object to `mu.init()` to override defaults:
|
|
|
607
652
|
|
|
608
653
|
```javascript
|
|
609
654
|
mu.init({
|
|
610
|
-
|
|
655
|
+
history: false,
|
|
611
656
|
processForms: false,
|
|
612
657
|
morph: false,
|
|
613
658
|
progress: true
|
|
@@ -618,13 +663,12 @@ mu.init({
|
|
|
618
663
|
|---|---|---|---|
|
|
619
664
|
| `processLinks` | bool | `true` | Intercept `<a>` tags. |
|
|
620
665
|
| `processForms` | bool | `true` | Intercept `<form>` tags. |
|
|
621
|
-
| `
|
|
622
|
-
| `ghostRedirect` | bool | `false` | Ghost mode for HTTP redirections. |
|
|
666
|
+
| `history` | bool | `true` | Add URL to browser history. |
|
|
623
667
|
| `mode` | string | `"replace"` | Default injection mode. |
|
|
624
668
|
| `target` | string | `"body"` | Default target CSS selector. |
|
|
625
669
|
| `source` | string | `"body"` | Default source CSS selector. |
|
|
626
670
|
| `title` | string | `"title"` | Title selector (`"selector"` or `"selector/attribute"`). |
|
|
627
|
-
| `
|
|
671
|
+
| `scroll` | bool\|null | `null` | Scroll behavior. `null` = auto (depends on mode and context). |
|
|
628
672
|
| `urlPrefix` | string\|null | `null` | Prefix added to fetched URLs. |
|
|
629
673
|
| `progress` | bool | `true` | Show progress bar during fetch. |
|
|
630
674
|
| `prefetch` | bool | `true` | Prefetch pages on link hover. |
|
|
@@ -637,7 +681,7 @@ mu.init({
|
|
|
637
681
|
|
|
638
682
|
```javascript
|
|
639
683
|
// Load a page programmatically
|
|
640
|
-
mu.load("/page", {
|
|
684
|
+
mu.load("/page", { history: false, target: "#content" });
|
|
641
685
|
|
|
642
686
|
// Get the last URL loaded by µJS
|
|
643
687
|
mu.getLastUrl(); // "/about" or null
|
|
@@ -658,17 +702,32 @@ mu.setMorph(function(target, html, opts) {
|
|
|
658
702
|
|
|
659
703
|
## Browser support
|
|
660
704
|
|
|
661
|
-
µJS works in all modern browsers
|
|
705
|
+
µJS works in all modern browsers. The minimum versions are determined by `AbortController` (used for request cancellation).
|
|
662
706
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
707
|
+
**Desktop:**
|
|
708
|
+
|
|
709
|
+
| Browser | Version | Release date |
|
|
710
|
+
|---|---|---|
|
|
711
|
+
| Chrome | 66+ | April 2018 |
|
|
712
|
+
| Edge | 79+ | January 2020 |
|
|
713
|
+
| Firefox | 57+ | November 2017 |
|
|
714
|
+
| Safari | 12.1+ | March 2019 |
|
|
715
|
+
| Opera | 53+ | May 2018 |
|
|
716
|
+
|
|
717
|
+
**Mobile:**
|
|
718
|
+
|
|
719
|
+
| Browser | Version | Release date |
|
|
720
|
+
|---|---|---|
|
|
721
|
+
| Chrome Android | 66+ | April 2018 |
|
|
722
|
+
| Safari iOS | 11.3+ | March 2018 |
|
|
723
|
+
| Firefox Android | 57+ | November 2017 |
|
|
724
|
+
| Opera Mobile | 47+ | May 2018 |
|
|
666
725
|
|
|
667
726
|
View Transitions require Chrome/Edge 111+. On unsupported browsers, transitions are skipped silently.
|
|
668
727
|
|
|
669
728
|
DOM morphing requires a separate library (idiomorph recommended). Without it, µJS falls back to direct DOM replacement.
|
|
670
729
|
|
|
671
|
-
µJS does **not** support Internet Explorer.
|
|
730
|
+
µJS does **not** support Internet Explorer or legacy Edge (EdgeHTML).
|
|
672
731
|
|
|
673
732
|
|
|
674
733
|
## License
|
package/dist/mu.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/* µJS (muJS) - mujs.org */
|
|
2
|
-
var mu=mu||new function(){this._VERSION="1.2.1",this._defaults={processLinks:!0,processForms:!0,ghost:!1,ghostRedirect:!1,mode:"replace",target:"body",source:"body",title:"title",scrollToTop:null,urlPrefix:null,progress:!0,prefetch:!0,prefetchTtl:3e3,morph:!0,transition:!0,confirmQuitText:"Are you sure you want to leave this page?"},this._cfg={},this._lastUrl=null,this._previousUrl=null,this._abortCtrl=null,this._progressEl=null,this._prefetchCache=new Map,this._confirmQuit=!1,this._jsIncludes={},this._morph=null,this._initialized=!1,this.init=function(t){if(mu._cfg=Object.assign({},mu._defaults,t||{}),mu._cfg._titleAttr=null,mu._cfg.title){var e=mu._cfg.title.lastIndexOf("/");-1!==e&&(mu._cfg._titleAttr=mu._cfg.title.substring(e+1),mu._cfg.title=mu._cfg.title.substring(0,e))}mu._morph||void 0===window.Idiomorph||"function"!=typeof window.Idiomorph.morph||(mu._morph=function(t,e,r){window.Idiomorph.morph(t,e,r)});for(var r=document.querySelectorAll("script[src]"),u=0;u<r.length;u++)mu._jsIncludes[r[u].getAttribute("src")]=!0;mu._initialized||(document.addEventListener("click",mu._onClick),document.addEventListener("submit",mu._onSubmit),document.addEventListener("mouseover",mu._onMouseOver),document.addEventListener("mouseout",mu._onMouseOut),document.addEventListener("input",mu._onInput),window.addEventListener("popstate",mu._onPopState),window.addEventListener("beforeunload",mu._onBeforeUnload),mu._initialized=!0),window.history.replaceState({mu:!0,url:location.pathname+location.search},""),document.body&&mu._initTriggers(document.body),mu._emit("mu:init",{url:location.pathname+location.search})},this.load=function(t,e){var r=Object.assign({},mu._cfg,e||{});mu._loadExec(t,r)},this.getLastUrl=function(){return mu._lastUrl},this.getPreviousUrl=function(){return mu._previousUrl},this.setConfirmQuit=function(t){mu._confirmQuit=!!t},this.setMorph=function(t){mu._morph=t},this._attr=function(t,e){return t.hasAttribute("mu-"+e)?t.getAttribute("mu-"+e):t.hasAttribute("data-mu-"+e)?t.getAttribute("data-mu-"+e):null},this._attrBool=function(t,e,r){var u=mu._attr(t,e);return null===u?r:""===u||"true"===u||"false"!==u&&r},this._shouldProcess=function(t){if("true"===mu._attr(t,"disabled")||""===mu._attr(t,"disabled"))return!1;if("false"===t.getAttribute("mu")||"false"===t.getAttribute("data-mu"))return!1;if(t.hasAttribute("target"))return!1;if("A"===t.tagName&&t.hasAttribute("onclick"))return!1;if("FORM"===t.tagName&&t.hasAttribute("onsubmit"))return!1;if("true"===t.getAttribute("mu")||"true"===t.getAttribute("data-mu"))return!0;var e=mu._attr(t,"url");if(null!==e)return!(!e.startsWith("/")||e.startsWith("//"));var r=t.getAttribute("href")||t.getAttribute("action")||"";return!(!r.startsWith("/")||r.startsWith("//"))},this._elemCfg=function(t){var e,r=Object.assign({},mu._cfg);if(null!==(e=mu._attr(t,"mode"))&&(r.mode=e),null!==(e=mu._attr(t,"target"))&&(r.target=e),null!==(e=mu._attr(t,"source"))&&(r.source=e),null!==(e=mu._attr(t,"title"))){r.title=e,r._titleAttr=null;var u=e.lastIndexOf("/");-1!==u&&(r._titleAttr=e.substring(u+1),r.title=e.substring(0,u))}return null!==(e=mu._attr(t,"url"))&&(r._url=e),null!==(e=mu._attr(t,"prefix"))&&(r.urlPrefix=e),r.ghost=mu._attrBool(t,"ghost",r.ghost),r.ghostRedirect=mu._attrBool(t,"ghost-redirect",r.ghostRedirect),r.scrollToTop=mu._attrBool(t,"scroll-to-top",r.scrollToTop),r.morph=mu._attrBool(t,"morph",r.morph),r.transition=mu._attrBool(t,"transition",r.transition),null!==(e=mu._attr(t,"method"))&&(r.method=e.toLowerCase()),!r.method&&mu._attrBool(t,"post",!1)&&(r.method="post"),r.confirm=mu._attr(t,"confirm"),r.patchGhost=mu._attrBool(t,"patch-ghost",!0),r},this._onClick=function(t){var e=t.target.closest("[mu-url], [data-mu-url], a");if(e&&mu._shouldProcess(e)&&"click"===mu._getTrigger(e)&&("A"!==e.tagName||mu._cfg.processLinks)&&!(t.ctrlKey||t.metaKey||t.shiftKey||t.altKey)){t.preventDefault();var r=mu._elemCfg(e),u=r._url||e.getAttribute("href");if(r._sourceElement=e,r.method||(r.method="get"),!r.confirm||window.confirm(r.confirm)){if(mu._confirmQuit){if(!window.confirm(r.confirmQuitText))return;mu.setConfirmQuit(!1)}"sse"!==r.method?mu._loadExec(u,r):mu._openSSE(u,e,r)}}},this._onSubmit=function(t){var e=t.target.closest("form");if(e&&mu._cfg.processForms&&mu._shouldProcess(e)&&"submit"===mu._getTrigger(e)&&e.reportValidity()){var r=mu._attr(e,"validate");if(!r||"function"!=typeof window[r]||window[r](e)){var u=mu._elemCfg(e),o=u.method||(e.getAttribute("method")||"get").toLowerCase();u.method=o;var i=u._url||e.getAttribute("action");if(u._sourceElement=e,"get"!==o)t.preventDefault(),u.postData=new FormData(e),e.hasAttribute("mu-ghost")||e.hasAttribute("data-mu-ghost")||(u.ghost=!0),null===u.scrollToTop&&"patch"!==u.mode&&(u.scrollToTop=!0);else{t.preventDefault();var n=new FormData(e);i=i+"?"+new URLSearchParams(n).toString()}mu.setConfirmQuit(!1),mu._loadExec(i,u)}}},this._onInput=function(t){t.target.closest("form[mu-confirm-quit], form[data-mu-confirm-quit]")&&mu.setConfirmQuit(!0)},this._onMouseOver=function(t){if(mu._cfg.prefetch){var e=t.target.closest("[mu-url], [data-mu-url], a");if(e&&mu._shouldProcess(e)&&"click"===mu._getTrigger(e)&&!1!==mu._attrBool(e,"prefetch",!0)){var r=mu._attr(e,"url")||e.getAttribute("href");if(r){var u=mu._prefetchCache.get(r);if(!(u&&Date.now()-u.ts<mu._cfg.prefetchTtl)&&r!==location.pathname+location.search){var o=mu._cfg.urlPrefix?mu._cfg.urlPrefix+r:r,i=fetch(o,{headers:{"X-Requested-With":"mujs","X-Mu-Prefetch":"1"},priority:"low"}).then(function(t){return t.ok?t.text():null}).catch(function(){return null});mu._prefetchCache.set(r,{promise:i,ts:Date.now()})}}}}},this._onMouseOut=function(t){},this._onPopState=function(t){var e=t.state;if(e&&e.mu){var r=Object.assign({},mu._cfg);r.ghost=!0,r.scrollToTop=!1,r._restoreScroll=void 0!==e.scrollX?{x:e.scrollX,y:e.scrollY}:null,mu._loadExec(e.url,r)}else window.location.href=document.location},this._onBeforeUnload=function(t){mu._confirmQuit&&(t.preventDefault(),t.returnValue=mu._cfg.confirmQuitText)},this._getTrigger=function(t){var e=mu._attr(t,"trigger");if(e)return e;var r=t.tagName;return"FORM"===r?"submit":"INPUT"===r||"TEXTAREA"===r||"SELECT"===r?"change":"click"},this._debounce=function(t,e){var r=null;return function(){clearTimeout(r),r=setTimeout(t,e)}},this._triggerAction=function(t){if(mu._shouldProcess(t)){var e=mu._elemCfg(t),r=e._url||t.getAttribute("href")||t.getAttribute("action");if(r){if(e._sourceElement=t,e._trigger=!0,e.transition=!1,e.method||(e.method="get"),t.hasAttribute("mu-ghost")||t.hasAttribute("data-mu-ghost")||(e.ghost=!0),"INPUT"===t.tagName||"TEXTAREA"===t.tagName||"SELECT"===t.tagName){var u=t.closest("form");if(u)if("get"===e.method){var o=new FormData(u),i=new URLSearchParams(o).toString();r=r.split("?")[0]+"?"+i}else e.postData=new FormData(u);else t.name&&"get"===e.method&&(r=r.split("?")[0]+"?"+encodeURIComponent(t.name)+"="+encodeURIComponent(t.value))}"sse"!==e.method?mu._loadExec(r,e):mu._openSSE(r,t,e)}}},this._initTriggers=function(t){for(var e=t.querySelectorAll("[mu-url], [data-mu-url], [mu-trigger], [data-mu-trigger]"),r=0;r<e.length;r++){var u=e[r];if(!u._mu_bound){var o=mu._getTrigger(u);if("click"!==o&&"submit"!==o)if(mu._attr(u,"url")||u.getAttribute("href")||u.getAttribute("action")){u._mu_bound=!0;var i=parseInt(mu._attr(u,"debounce"),10)||0,n=parseInt(mu._attr(u,"repeat"),10)||0,s=function(t){return function(){mu._triggerAction(t)}}(u);if(i>0&&(s=mu._debounce(s,i)),n>0&&(s=function(t,e,r){var u=!1;return function(){e(),u||(u=!0,t._mu_interval=setInterval(e,r))}}(u,s,n)),"change"===o)u.addEventListener("input",s);else if("blur"===o){var a=function(t){var e=0;return function(){var r=Date.now();r-e<50||(e=r,t())}}(s);u.addEventListener("change",a),u.addEventListener("blur",a)}else"focus"===o?u.addEventListener("focus",s):"load"===o&&s()}}}},this._cleanupTriggers=function(t){for(var e=t.querySelectorAll?t.querySelectorAll("*"):[],r=0;r<e.length;r++)e[r]._mu_interval&&(clearInterval(e[r]._mu_interval),e[r]._mu_interval=null),e[r]._mu_sse&&(e[r]._mu_sse.close(),e[r]._mu_sse=null);t._mu_interval&&(clearInterval(t._mu_interval),t._mu_interval=null),t._mu_sse&&(t._mu_sse.close(),t._mu_sse=null)},this._openSSE=function(t,e,r){e._mu_sse&&e._mu_sse.close();var u=r.urlPrefix?r.urlPrefix+t:t,o=new EventSource(u);e._mu_sse=o,o.onmessage=function(e){var u={url:t,html:e.data,config:r};mu._emit("mu:before-render",u)&&("patch"===r.mode?mu._renderPatch(u.html,r):mu._renderPage(u.html,r),mu._emit("mu:after-render",{url:t,finalUrl:t,mode:r.mode}))},o.onerror=function(){mu._emit("mu:fetch-error",{url:t,fetchUrl:u,error:new Error("SSE connection error")})}},this._loadExec=async function(t,e){var r=e.urlPrefix?e.urlPrefix+t:t;if(e._trigger||mu._saveScroll(),mu._emit("mu:before-fetch",{url:t,fetchUrl:r,config:e,sourceElement:e._sourceElement||null})){var u;e._trigger?u=new AbortController:(mu._abortCtrl&&mu._abortCtrl.abort(),u=mu._abortCtrl=new AbortController),e._trigger||mu._showProgress();try{var o=null,i=null,n=t,s=mu._prefetchCache.get(t);if(s&&s.promise&&Date.now()-s.ts<mu._cfg.prefetchTtl&&(o=await s.promise,u.signal.aborted))return;if(!o){var a={signal:u.signal,headers:{"X-Requested-With":"mujs","X-Mu-Mode":e.mode}},l=(e.method||"get").toUpperCase();if("GET"!==l&&(a.method=l,a.headers["X-Mu-Method"]=l,e.postData&&(a.body=e.postData)),!(i=await fetch(r,a)).ok)return void mu._emit("mu:fetch-error",{url:t,fetchUrl:r,status:i.status,response:i});i.redirected&&(n=new URL(i.url).pathname+new URL(i.url).search),o=await i.text()}e._trigger||mu._prefetchCache.set(t,{promise:Promise.resolve(o),ts:Date.now()});var m,c={url:t,finalUrl:n,html:o,config:e};if(!mu._emit("mu:before-render",c))return;if(m="patch"===e.mode?function(){mu._renderPatch(c.html,e)}:function(){mu._renderPage(c.html,e)},e.transition&&document.startViewTransition?document.startViewTransition(m):m(),"patch"===e.mode)e.patchGhost||(mu._previousUrl=mu._lastUrl,mu._lastUrl=n,window.history.pushState({mu:!0,url:n},"",n));else e.ghost||i&&i.redirected&&e.ghostRedirect||e.postData?i&&i.redirected&&!e.ghostRedirect?(mu._previousUrl=mu._lastUrl,mu._lastUrl=n,window.history.pushState({mu:!0,url:n},"",n)):(mu._previousUrl=mu._lastUrl,mu._lastUrl=n):(mu._previousUrl=mu._lastUrl,mu._lastUrl=n,window.history.pushState({mu:!0,url:n},"",n));if("patch"!==e.mode)if(e._restoreScroll)window.scrollTo(e._restoreScroll.x,e._restoreScroll.y);else{var h=e.ghost||i&&i.redirected&&e.ghostRedirect;if(null!==e.scrollToTop?e.scrollToTop:!h){var _=t.indexOf("#");if(-1!==_){var d=document.getElementById(t.substring(_+1));d&&d.scrollIntoView({behavior:"smooth"})}else window.scrollTo(0,0)}}mu.setConfirmQuit(!1),mu._emit("mu:after-render",{url:t,finalUrl:n,mode:e.mode})}catch(e){if("AbortError"===e.name)return;mu._emit("mu:fetch-error",{url:t,fetchUrl:r,error:e})}finally{e._trigger||mu._hideProgress()}}},this._renderPage=function(t,e){var r=(new DOMParser).parseFromString(t,"text/html"),u=null;e.source&&(u=r.querySelector(e.source)),u||(u=r.body);var o=document.querySelector(e.target);if(o){mu._cleanupTriggers(o),mu._applyMode(e.mode,o,u,e),e.ghost||mu._updateTitle(r,e),mu._mergeHead(r);var i=document.querySelector(e.target)||document.body;mu._runScripts(i),mu._initTriggers(i)}else console.warn("[µJS] Target element '"+e.target+"' not found.")},this._renderPatch=function(t,e){for(var r=(new DOMParser).parseFromString(t,"text/html").querySelectorAll("[mu-patch-target], [data-mu-patch-target]"),u=[],o=0;o<r.length;o++){var i=r[o],n=i.getAttribute("mu-patch-target")||i.getAttribute("data-mu-patch-target"),s=i.getAttribute("mu-patch-mode")||i.getAttribute("data-mu-patch-mode")||"replace",a=document.querySelector(n);a?(mu._cleanupTriggers(a),mu._applyMode(s,a,i,e),"remove"!==s&&(mu._runScripts(i),u.push(n))):console.warn("[µJS] Patch target '"+n+"' not found.")}for(var l=0;l<u.length;l++){var m=document.querySelector(u[l]);m&&mu._initTriggers(m)}},this._applyMode=function(t,e,r,u){var o=u.morph&&mu._morph;switch(t){case"update":o?mu._morph(e,r.innerHTML,{morphStyle:"innerHTML"}):e.innerHTML=r.innerHTML;break;case"prepend":e.prepend(r);break;case"append":e.append(r);break;case"before":e.before(r);break;case"after":e.after(r);break;case"remove":e.remove();break;case"none":break;default:"BODY"===e.tagName&&"BODY"===r.tagName?o?mu._morph(e,r.innerHTML,{morphStyle:"innerHTML"}):e.innerHTML=r.innerHTML:o?mu._morph(e,r.outerHTML,{morphStyle:"outerHTML"}):e.replaceWith(r)}},this._updateTitle=function(t,e){if(e.title){var r=t.querySelector(e.title);if(r){var u=e._titleAttr?r.getAttribute(e._titleAttr):r.textContent;u&&(document.title=u)}}},this._mergeHead=function(t){for(var e="link[rel='stylesheet'], style, script",r=document.head.querySelectorAll(e),u=t.head.querySelectorAll(e),o=new Set,i=0;i<r.length;i++)o.add(mu._elKey(r[i]));for(i=0;i<u.length;i++)if(!o.has(mu._elKey(u[i])))if("SCRIPT"===u[i].tagName){for(var n=document.createElement("script"),s=0;s<u[i].attributes.length;s++)n.setAttribute(u[i].attributes[s].name,u[i].attributes[s].value);n.textContent=u[i].textContent,n.hasAttribute("src")&&(mu._jsIncludes[n.getAttribute("src")]=!0),document.head.appendChild(n)}else document.head.appendChild(u[i].cloneNode(!0))},this._elKey=function(t){return"LINK"===t.tagName?"link:"+t.getAttribute("href"):"STYLE"===t.tagName?"style:"+t.textContent.substring(0,100):"SCRIPT"===t.tagName?"script:"+(t.getAttribute("src")||t.textContent.substring(0,100)):t.outerHTML},this._runScripts=function(t){for(var e=t.querySelectorAll("script"),r=0;r<e.length;r++){var u=e[r];if("true"!==mu._attr(u,"disabled")&&""!==mu._attr(u,"disabled")){if(u.hasAttribute("src")){var o=u.getAttribute("src");if(mu._jsIncludes[o])continue;mu._jsIncludes[o]=!0}for(var i=document.createElement("script"),n=0;n<u.attributes.length;n++)i.setAttribute(u.attributes[n].name,u.attributes[n].value);i.textContent=u.textContent,u.parentNode.replaceChild(i,u)}}},this._showProgress=function(){if(mu._cfg.progress){if(!mu._progressEl){mu._progressEl=document.createElement("div"),mu._progressEl.id="mu-progress";var t=mu._progressEl.style;t.position="fixed",t.top="0",t.left="0",t.height="3px",t.background="#29d",t.zIndex="99999",t.transition="width .3s ease",t.width="0"}document.body.appendChild(mu._progressEl),mu._progressEl.offsetWidth,mu._progressEl.style.width="70%"}},this._hideProgress=function(){mu._progressEl&&(mu._progressEl.style.width="100%",setTimeout(function(){mu._progressEl&&(mu._progressEl.style.transition="none",mu._progressEl.style.width="0",mu._progressEl.offsetWidth,mu._progressEl.style.transition="width .3s ease",mu._progressEl.remove())},200))},this._saveScroll=function(){var t=window.history.state;t&&t.mu&&(t.scrollX=window.scrollX,t.scrollY=window.scrollY,window.history.replaceState(t,""))},this._emit=function(t,e){(e=e||{}).lastUrl=mu._lastUrl,e.previousUrl=mu._previousUrl;var r=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:e});return document.dispatchEvent(r)}};
|
|
2
|
+
var mu=mu||new function(){this._VERSION="1.4.1",this._defaults={processLinks:!0,processForms:!0,history:!0,mode:"replace",target:"body",source:"body",title:"title",scroll:null,urlPrefix:null,progress:!0,prefetch:!0,prefetchTtl:3e3,morph:!0,transition:!0,confirmQuitText:"Are you sure you want to leave this page?"},this._cfg={},this._lastUrl=null,this._previousUrl=null,this._abortCtrl=null,this._progressEl=null,this._prefetchCache=new Map,this._prefetchTimer=null,this._confirmQuit=!1,this._jsIncludes={},this._morph=null,this._initialized=!1,this.init=function(t){if(mu._cfg=Object.assign({},mu._defaults,t||{}),mu._cfg._titleAttr=null,mu._cfg.title){var e=mu._cfg.title.lastIndexOf("/");-1!==e&&(mu._cfg._titleAttr=mu._cfg.title.substring(e+1),mu._cfg.title=mu._cfg.title.substring(0,e))}mu._morph||void 0===window.Idiomorph||"function"!=typeof window.Idiomorph.morph||(mu._morph=function(t,e,r){window.Idiomorph.morph(t,e,r)});for(var r=document.querySelectorAll("script[src]"),u=0;u<r.length;u++)mu._jsIncludes[r[u].getAttribute("src")]=!0;mu._initialized||(document.addEventListener("click",mu._onClick),document.addEventListener("submit",mu._onSubmit),document.addEventListener("mouseover",mu._onMouseOver),document.addEventListener("mouseout",mu._onMouseOut),document.addEventListener("input",mu._onInput),window.addEventListener("popstate",mu._onPopState),window.addEventListener("beforeunload",mu._onBeforeUnload),mu._initialized=!0),window.history.replaceState({mu:!0,url:location.pathname+location.search},""),document.body&&mu._initTriggers(document.body),mu._emit("mu:init",{url:location.pathname+location.search})},this.load=function(t,e){var r=Object.assign({},mu._cfg,e||{});mu._loadExec(t,r)},this.getLastUrl=function(){return mu._lastUrl},this.getPreviousUrl=function(){return mu._previousUrl},this.setConfirmQuit=function(t){mu._confirmQuit=!!t},this.setMorph=function(t){mu._morph=t},this._attr=function(t,e){return t.hasAttribute("mu-"+e)?t.getAttribute("mu-"+e):t.hasAttribute("data-mu-"+e)?t.getAttribute("data-mu-"+e):null},this._attrBool=function(t,e,r){var u=mu._attr(t,e);return null===u?r:""===u||"true"===u||"false"!==u&&r},this._shouldProcess=function(t){if("true"===mu._attr(t,"disabled")||""===mu._attr(t,"disabled"))return!1;if("false"===t.getAttribute("mu")||"false"===t.getAttribute("data-mu"))return!1;if(t.hasAttribute("target"))return!1;if(t.hasAttribute("download"))return!1;if("A"===t.tagName&&t.hasAttribute("onclick"))return!1;if("FORM"===t.tagName&&t.hasAttribute("onsubmit"))return!1;if("true"===t.getAttribute("mu")||"true"===t.getAttribute("data-mu"))return!0;var e=mu._attr(t,"url");if(null!==e)return!(!e.startsWith("/")||e.startsWith("//"));var r=t.getAttribute("href")||t.getAttribute("action")||"";return!(!r.startsWith("/")||r.startsWith("//"))},this._elemCfg=function(t){var e,r=Object.assign({},mu._cfg);if(null!==(e=mu._attr(t,"mode"))&&(r.mode=e),null!==(e=mu._attr(t,"target"))&&(r.target=e),null!==(e=mu._attr(t,"source"))&&(r.source=e),null!==(e=mu._attr(t,"title"))){r.title=e,r._titleAttr=null;var u=e.lastIndexOf("/");-1!==u&&(r._titleAttr=e.substring(u+1),r.title=e.substring(0,u))}return null!==(e=mu._attr(t,"url"))&&(r._url=e),null!==(e=mu._attr(t,"prefix"))&&(r.urlPrefix=e),r.history=mu._attrBool(t,"history",r.history),r.scroll=mu._attrBool(t,"scroll",r.scroll),r.morph=mu._attrBool(t,"morph",r.morph),r.transition=mu._attrBool(t,"transition",r.transition),null!==(e=mu._attr(t,"method"))&&(r.method=e.toLowerCase()),r.confirm=mu._attr(t,"confirm"),r.patchHistory=mu._attrBool(t,"patch-history",!1),"replace"!==r.mode&&"update"!==r.mode&&"patch"!==r.mode&&(t.hasAttribute("mu-history")||t.hasAttribute("data-mu-history")||(r.history=!1),t.hasAttribute("mu-scroll")||t.hasAttribute("data-mu-scroll")||null!==r.scroll||(r.scroll=!1)),r},this._onClick=function(t){var e=t.target.closest("[mu-url], [data-mu-url], a");if(e&&mu._shouldProcess(e)&&"click"===mu._getTrigger(e)&&("A"!==e.tagName||mu._cfg.processLinks)&&!(t.ctrlKey||t.metaKey||t.shiftKey||t.altKey)){t.preventDefault();var r=mu._elemCfg(e),u=r._url||e.getAttribute("href");if(r._sourceElement=e,r.method||(r.method="get"),!r.confirm||window.confirm(r.confirm)){if(mu._confirmQuit){if(!window.confirm(r.confirmQuitText))return;mu.setConfirmQuit(!1)}"sse"!==r.method?mu._loadExec(u,r):mu._openSSE(u,e,r)}}},this._onSubmit=function(t){var e=t.target.closest("form");if(e&&mu._cfg.processForms&&mu._shouldProcess(e)&&"submit"===mu._getTrigger(e)&&e.reportValidity()){var r=mu._attr(e,"validate");if(!r||"function"!=typeof window[r]||window[r](e)){var u=mu._elemCfg(e),o=u.method||(e.getAttribute("method")||"get").toLowerCase();u.method=o;var i=u._url||e.getAttribute("action");if(u._sourceElement=e,"get"!==o)t.preventDefault(),u.postData=new FormData(e),e.hasAttribute("mu-history")||e.hasAttribute("data-mu-history")||(u.history=!1),null===u.scroll&&"patch"!==u.mode&&(u.scroll=!0);else{t.preventDefault();var n=new FormData(e);i=i+"?"+new URLSearchParams(n).toString()}mu.setConfirmQuit(!1),mu._loadExec(i,u)}}},this._onInput=function(t){t.target.closest("form[mu-confirm-quit], form[data-mu-confirm-quit]")&&mu.setConfirmQuit(!0)},this._onMouseOver=function(t){if(mu._cfg.prefetch){var e=t.target.closest("[mu-url], [data-mu-url], a");if(e&&mu._shouldProcess(e)&&"click"===mu._getTrigger(e)){var r=mu._attr(e,"method");if((!r||"get"===r.toLowerCase())&&!1!==mu._attrBool(e,"prefetch",!0)){var u=mu._attr(e,"url")||e.getAttribute("href");if(u){var o=mu._prefetchCache.get(u);o&&Date.now()-o.ts<mu._cfg.prefetchTtl||u!==location.pathname+location.search&&(clearTimeout(mu._prefetchTimer),mu._prefetchTimer=setTimeout(function(){mu._prefetchTimer=null;var t=mu._prefetchCache.get(u);if(!(t&&Date.now()-t.ts<mu._cfg.prefetchTtl)){var e=mu._cfg.urlPrefix?mu._cfg.urlPrefix+u:u,r=fetch(e,{headers:{"X-Requested-With":"mujs","X-Mu-Prefetch":"1"},priority:"low"}).then(function(t){return t.ok?t.text():null}).catch(function(){return null});mu._prefetchCache.set(u,{promise:r,ts:Date.now()})}},50))}}}}},this._onMouseOut=function(t){mu._prefetchTimer&&(clearTimeout(mu._prefetchTimer),mu._prefetchTimer=null)},this._onPopState=function(t){var e=t.state;if(e&&e.mu){var r=Object.assign({},mu._cfg);r.history=!1,r.scroll=!1,r._restoreScroll=void 0!==e.scrollX?{x:e.scrollX,y:e.scrollY}:null,mu._loadExec(e.url,r)}else window.location.href=document.location},this._onBeforeUnload=function(t){mu._confirmQuit&&(t.preventDefault(),t.returnValue=mu._cfg.confirmQuitText)},this._getTrigger=function(t){var e=mu._attr(t,"trigger");if(e)return e;var r=t.tagName;return"FORM"===r?"submit":"INPUT"===r||"TEXTAREA"===r||"SELECT"===r?"change":"click"},this._debounce=function(t,e){var r=null;return function(){clearTimeout(r),r=setTimeout(t,e)}},this._triggerAction=function(t){if(mu._shouldProcess(t)){var e=mu._elemCfg(t),r=e._url||t.getAttribute("href")||t.getAttribute("action");if(r){if(e._sourceElement=t,e._trigger=!0,e.transition=!1,e.method||(e.method="get"),t.hasAttribute("mu-history")||t.hasAttribute("data-mu-history")||(e.history=!1),t.hasAttribute("mu-scroll")||t.hasAttribute("data-mu-scroll")||null!==e.scroll||(e.scroll=!1),"INPUT"===t.tagName||"TEXTAREA"===t.tagName||"SELECT"===t.tagName){var u=t.closest("form");if(u)if("get"===e.method){var o=new FormData(u),i=new URLSearchParams(o).toString();r=r.split("?")[0]+"?"+i}else e.postData=new FormData(u);else t.name&&"get"===e.method&&(r=r.split("?")[0]+"?"+encodeURIComponent(t.name)+"="+encodeURIComponent(t.value))}"sse"!==e.method?mu._loadExec(r,e):mu._openSSE(r,t,e)}}},this._initTriggers=function(t){for(var e=t.querySelectorAll("[mu-url], [data-mu-url], [mu-trigger], [data-mu-trigger]"),r=0;r<e.length;r++){var u=e[r];if(!u._mu_bound){var o=mu._getTrigger(u);if("click"!==o&&"submit"!==o)if(mu._attr(u,"url")||u.getAttribute("href")||u.getAttribute("action")){u._mu_bound=!0;var i=parseInt(mu._attr(u,"debounce"),10)||0,n=parseInt(mu._attr(u,"repeat"),10)||0,a=function(t){return function(){mu._triggerAction(t)}}(u);if(i>0&&(a=mu._debounce(a,i)),n>0&&(a=function(t,e,r){var u=!1;return function(){e(),u||(u=!0,t._mu_interval=setInterval(e,r))}}(u,a,n)),"change"===o)u.addEventListener("input",a);else if("blur"===o){var s=function(t){var e=0;return function(){var r=Date.now();r-e<50||(e=r,t())}}(a);u.addEventListener("change",s),u.addEventListener("blur",s)}else"focus"===o?u.addEventListener("focus",a):"load"===o&&a()}}}},this._cleanupTriggers=function(t){for(var e=t.querySelectorAll?t.querySelectorAll("*"):[],r=0;r<e.length;r++)e[r]._mu_interval&&(clearInterval(e[r]._mu_interval),e[r]._mu_interval=null),e[r]._mu_sse&&(e[r]._mu_sse.close(),e[r]._mu_sse=null);t._mu_interval&&(clearInterval(t._mu_interval),t._mu_interval=null),t._mu_sse&&(t._mu_sse.close(),t._mu_sse=null)},this._openSSE=function(t,e,r){e._mu_sse&&e._mu_sse.close();var u=r.urlPrefix?r.urlPrefix+t:t,o=new EventSource(u);e._mu_sse=o,o.onmessage=function(e){var u={url:t,html:e.data,config:r};mu._emit("mu:before-render",u)&&("patch"===r.mode?mu._renderPatch(u.html,r):mu._renderPage(u.html,r),mu._emit("mu:after-render",{url:t,finalUrl:t,mode:r.mode}))},o.onerror=function(){mu._emit("mu:fetch-error",{url:t,fetchUrl:u,error:new Error("SSE connection error")})}},this._loadExec=async function(t,e){var r=e.urlPrefix?e.urlPrefix+t:t;if(e._trigger||mu._saveScroll(),mu._emit("mu:before-fetch",{url:t,fetchUrl:r,config:e,sourceElement:e._sourceElement||null})){var u;e._trigger?u=new AbortController:(mu._abortCtrl&&mu._abortCtrl.abort(),u=mu._abortCtrl=new AbortController),e._trigger||mu._showProgress();try{var o=null,i=null,n=t,a=mu._prefetchCache.get(t);if(a&&a.promise&&Date.now()-a.ts<mu._cfg.prefetchTtl&&(o=await a.promise,u.signal.aborted))return;if(!o){var s={signal:u.signal,headers:{"X-Requested-With":"mujs","X-Mu-Mode":e.mode}},l=(e.method||"get").toUpperCase();if("GET"!==l&&(s.method=l,s.headers["X-Mu-Method"]=l,e.postData&&(s.body=e.postData)),!(i=await fetch(r,s)).ok)return void mu._emit("mu:fetch-error",{url:t,fetchUrl:r,status:i.status,response:i});i.redirected&&(n=new URL(i.url).pathname+new URL(i.url).search),o=await i.text()}e._trigger||mu._prefetchCache.set(t,{promise:Promise.resolve(o),ts:Date.now()});var m,c={url:t,finalUrl:n,html:o,config:e};if(!mu._emit("mu:before-render",c))return;if("patch"===e.mode?e._addHistory=e.patchHistory:(e._addHistory=e.history,i&&i.redirected&&(e._addHistory=!0)),m="patch"===e.mode?function(){mu._renderPatch(c.html,e)}:function(){mu._renderPage(c.html,e)},e.transition&&document.startViewTransition?document.startViewTransition(m):m(),mu._previousUrl=mu._lastUrl,mu._lastUrl=n,e._addHistory&&window.history.pushState({mu:!0,url:n},"",n),"patch"!==e.mode)if(e._restoreScroll)window.scrollTo(e._restoreScroll.x,e._restoreScroll.y);else if(null===e.scroll||e.scroll){var h=t.indexOf("#");if(-1!==h){var _=document.getElementById(t.substring(h+1));_&&_.scrollIntoView({behavior:"smooth"})}else window.scrollTo(0,0)}mu.setConfirmQuit(!1),mu._emit("mu:after-render",{url:t,finalUrl:n,mode:e.mode})}catch(e){if("AbortError"===e.name)return;mu._emit("mu:fetch-error",{url:t,fetchUrl:r,error:e})}finally{e._trigger||mu._hideProgress()}}},this._renderPage=function(t,e){var r=(new DOMParser).parseFromString(t,"text/html"),u=null;e.source&&(u=r.querySelector(e.source)),u||(u=r.body);var o=document.querySelector(e.target);if(o){mu._cleanupTriggers(o),mu._applyMode(e.mode,o,u,e),e._addHistory&&mu._updateTitle(r,e),mu._mergeHead(r);var i=document.querySelector(e.target)||document.body;mu._runScripts(i),mu._initTriggers(i)}else console.warn("[µJS] Target element '"+e.target+"' not found.")},this._renderPatch=function(t,e){for(var r=(new DOMParser).parseFromString(t,"text/html").querySelectorAll("[mu-patch-target], [data-mu-patch-target]"),u=[],o=0;o<r.length;o++){var i=r[o],n=i.getAttribute("mu-patch-target")||i.getAttribute("data-mu-patch-target"),a=i.getAttribute("mu-patch-mode")||i.getAttribute("data-mu-patch-mode")||"replace",s=document.querySelector(n);s?(mu._cleanupTriggers(s),mu._applyMode(a,s,i,e),"remove"!==a&&(mu._runScripts(i),u.push(n))):console.warn("[µJS] Patch target '"+n+"' not found.")}for(var l=0;l<u.length;l++){var m=document.querySelector(u[l]);m&&mu._initTriggers(m)}},this._applyMode=function(t,e,r,u){var o=u.morph&&mu._morph;switch(t){case"update":o?mu._morph(e,r.innerHTML,{morphStyle:"innerHTML"}):e.innerHTML=r.innerHTML;break;case"prepend":e.prepend(r);break;case"append":e.append(r);break;case"before":e.before(r);break;case"after":e.after(r);break;case"remove":e.remove();break;case"none":break;default:"BODY"===e.tagName&&"BODY"===r.tagName?o?mu._morph(e,r.innerHTML,{morphStyle:"innerHTML"}):e.innerHTML=r.innerHTML:o?mu._morph(e,r.outerHTML,{morphStyle:"outerHTML"}):e.replaceWith(r)}},this._updateTitle=function(t,e){if(e.title){var r=t.querySelector(e.title);if(r){var u=e._titleAttr?r.getAttribute(e._titleAttr):r.textContent;u&&(document.title=u)}}},this._mergeHead=function(t){for(var e="link[rel='stylesheet'], style, script",r=document.head.querySelectorAll(e),u=t.head.querySelectorAll(e),o=new Set,i=0;i<r.length;i++)o.add(mu._elKey(r[i]));for(i=0;i<u.length;i++)if(!o.has(mu._elKey(u[i])))if("SCRIPT"===u[i].tagName){for(var n=document.createElement("script"),a=0;a<u[i].attributes.length;a++)n.setAttribute(u[i].attributes[a].name,u[i].attributes[a].value);n.textContent=u[i].textContent,n.hasAttribute("src")&&(mu._jsIncludes[n.getAttribute("src")]=!0),document.head.appendChild(n)}else document.head.appendChild(u[i].cloneNode(!0))},this._elKey=function(t){return"LINK"===t.tagName?"link:"+t.getAttribute("href"):"STYLE"===t.tagName?"style:"+t.textContent.substring(0,100):"SCRIPT"===t.tagName?"script:"+(t.getAttribute("src")||t.textContent.substring(0,100)):t.outerHTML},this._runScripts=function(t){for(var e=t.querySelectorAll("script"),r=0;r<e.length;r++){var u=e[r];if("true"!==mu._attr(u,"disabled")&&""!==mu._attr(u,"disabled")){if(u.hasAttribute("src")){var o=u.getAttribute("src");if(mu._jsIncludes[o])continue;mu._jsIncludes[o]=!0}for(var i=document.createElement("script"),n=0;n<u.attributes.length;n++)i.setAttribute(u.attributes[n].name,u.attributes[n].value);i.textContent=u.textContent,u.parentNode.replaceChild(i,u)}}},this._showProgress=function(){if(mu._cfg.progress){if(!mu._progressEl){mu._progressEl=document.createElement("div"),mu._progressEl.id="mu-progress";var t=mu._progressEl.style;t.position="fixed",t.top="0",t.left="0",t.height="3px",t.background="#29d",t.zIndex="99999",t.transition="width .3s ease",t.width="0"}document.body.appendChild(mu._progressEl),mu._progressEl.offsetWidth,mu._progressEl.style.width="70%"}},this._hideProgress=function(){mu._progressEl&&(mu._progressEl.style.width="100%",setTimeout(function(){mu._progressEl&&(mu._progressEl.style.transition="none",mu._progressEl.style.width="0",mu._progressEl.offsetWidth,mu._progressEl.style.transition="width .3s ease",mu._progressEl.remove())},200))},this._saveScroll=function(){var t=window.history.state;t&&t.mu&&(t.scrollX=window.scrollX,t.scrollY=window.scrollY,window.history.replaceState(t,""))},this._emit=function(t,e){(e=e||{}).lastUrl=mu._lastUrl,e.previousUrl=mu._previousUrl;var r=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:e});return document.dispatchEvent(r)}};
|