@digicreon/mujs 1.4.0 → 1.4.2

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 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, ~10 KB gzipped, zero dependencies
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
@@ -33,6 +33,7 @@ Inspired by [pjax](https://github.com/defunkt/jquery-pjax), [Turbo](https://turb
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="/file.pdf" mu-disabled>Download PDF</a>
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>
@@ -512,6 +519,33 @@ Enabled by default. Falls back silently on unsupported browsers.
512
519
  ```
513
520
 
514
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
+
515
549
  ## Progress bar
516
550
 
517
551
  A thin progress bar (3px, blue) is displayed at the top of the page during fetch requests. It requires no external stylesheet.
@@ -668,17 +702,32 @@ mu.setMorph(function(target, html, opts) {
668
702
 
669
703
  ## Browser support
670
704
 
671
- µJS works in all modern browsers:
705
+ µJS works in all modern browsers. The minimum versions are determined by `AbortController` (used for request cancellation).
706
+
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:**
672
718
 
673
- - Chrome / Edge 89+
674
- - Firefox 87+
675
- - Safari 15+
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 |
676
725
 
677
726
  View Transitions require Chrome/Edge 111+. On unsupported browsers, transitions are skipped silently.
678
727
 
679
728
  DOM morphing requires a separate library (idiomorph recommended). Without it, µJS falls back to direct DOM replacement.
680
729
 
681
- µJS does **not** support Internet Explorer.
730
+ µJS does **not** support Internet Explorer or legacy Edge (EdgeHTML).
682
731
 
683
732
 
684
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.4.0",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("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)}};
2
+ var mu=mu||new function(){this._VERSION="1.4.2",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),"loading"===document.readyState&&document.addEventListener("DOMContentLoaded",function(){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 d=t.indexOf("#");if(-1!==d){var h=document.getElementById(t.substring(d+1));h&&h.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)}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digicreon/mujs",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Lightweight AJAX navigation library",
5
5
  "main": "dist/mu.min.js",
6
6
  "files": [