UNPKG

lockandload

Version:

Minimalist AMD-compliant Javascript and CSS loader

244 lines (243 loc) 9.03 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <!-- The following <script> *must* stay at the top --> <!-- Cut BEGIN for lockandload_master.inc --> <script> // License: ISC OR GPL-3.0 ((W,D,F,X,M,L,R)=> // lockandload v3.2: boilerplate AMD-loader { "use strict"; // Copyright (c) 2025 <srb@cuci.nl> // // Integrate GTM support to get the timing right // W.dataLayer=[{"gtm.start":Date.now(),event:"gtm.js"}]; R[X]=R[M]=R; // DEBUG_START var reqcnt = 2; // DEBUG_END // // self-contained AMD define() // function E(n,d,f,j) { function c(k,i) // // Iterate through dependencies, count and postpone unresolved // { for (i of k||[]) if (L[i]||!R[i]) j++, (L[i]=L[i]||[]).push(c); // DEBUG_START if (j > 1) console.log("Dependencies left(" + JSON.stringify(n) + ") = " + (j-1)); // DEBUG_END if (!--j) // // All dependencies have been resolved: in situ replacement // { R[X]=R[n]; for (i in d) d[i]=R[d[i]]; // DEBUG_START console.log("=============== Running(" + JSON.stringify(n) + ")"); // DEBUG_END // // Run factory exactly once. // Support non-function factories. // Assume "exports" if the factory returns 0 // R[n]=(typeof f=="function"?f.apply(0,d):f)||R[X]; // // Early release of factory function for garbage collection // d=L[n]||[]; delete L[n]; // // Resolve dependents // while (f=d.pop()) f(); } } // // Restructure argument ordering // if (!f) if (f=d, d=0, !f) f=n, n=0; else if (Array.isArray(n)) d=n, n=0; // // Support anonymous definitions // if (!n) { n=D.currentScript.src.match(/([-\w_]+(?:\.[-\w_]+)*)\.js(?:[^\w]|$)/)[1]; if (j=n.match(/(.*)\.min$/)) n=j[1]; } // DEBUG_START if (n === 1) n = reqcnt++; console.log("define(" + JSON.stringify(n) + "," + JSON.stringify(d) + "," + (typeof f == "function"?f.toString():JSON.stringify(f)) .substr(0, 80).replace(/\s+/g, " ") + ")"); // DEBUG_END // // Initialise exports, mark it as unresolved and off to the races // j=1; R[n]={}; L[n]=L[n]||[]; c(d=d||[F,X,M]); } // AMD-loader compliance (W.define=E).amd={lockandload:E||"v3.2, Copyright (c) 2025 <srb@cuci.nl>"}; // // Global require() // W[F]=(d,f)=>f?E(1,d,f):R[d]; // // $$(on every SPA-page switch) // Run per definition if already triggered E.S=[0]; W.$$=(f)=>(E.S.push(f),E.S[0]&&f(1)); // $(on initial page load) E.Q=[]; W.$=(f)=>E.Q.push(f); })(window,document,"require","exports","module",{},{}); </script> <!-- Cut END for lockandload_master.inc --> <!-- All high priority Javascript files go here --> <script importance="high" src="main.js" async></script> <meta name="viewport" content="width=device-width,initial-scale=1" /> <!-- All high priority CSS files go here --> <link rel="stylesheet" href="css/main.css" /> <title>Lock and load</title> <meta name="description" value="Minimalist AMD-compliant Javascript and CSS loader" /> <!-- This is where the you put all the other tags that go into <head> --> <!-- Cut BEGIN for lockandload_headready.inc --> <script> // // Provide local shortcuts to W=window, D=document, E=define // Declare a housekeeping variable P to store declared jsa() aliases. // ((W,D,F,E,P)=> { "use strict"; // // Add gtag() convenience function for gtag.js users. // Cannot use => function declaration syntax due to use of "arguments". // W.gtag=function(){ dataLayer.push(arguments); }; // // Helper function to add new entries at the end of the <head> // function n(e,a,v,r,u,p,x,y,k) { k=D.createElement(e); if(p) k.onload=()=>E(p, 1); k.fetchPriority="low"; k[a]=v; k[r]=u; x||(k.crossOrigin=""); for (x in y) k.setAttribute(x, y[x]); D.head.appendChild(k); } // // css(url): asynchronously load low priority CSS stylesheets // css(url, id): same as above, but also fulfill dependency id after // the rules have been applied. // function css(u,p){ n("link","rel","stylesheet","href",u,p); } // // js(url): load Javascript files sequentially in the background // js(url, "async"): load low priority Javascript files asynchronously // js(url, "async", 1): like above, but without CORS (e.g. for GTM) // js(url, "async", 0, {"data-attr1":"test"}): like the second, but // with an object-parameter describing a number of attributes. // We attempt to deduplicate against existing earlier entries. // function js(u,a,x,y) { if (!D.head.querySelector(`script[src="${u}"]`)) n("script","async",a,"src",u,0,x,y); } // // jsa(alias, path); define aliases for javascript file paths // to be referenced through require.load(alias) to load the file on demand // function jsa(a,p){ P[a]=p; } /* Cut END for lockandload_headready.inc */ /* ** This is the start of your config area. Customise to taste. ** ** Define a bunch of pathname aliases to reference javascript files that ** shall be loaded through require.load(path) on demand. ** Specifying those here now avoids sprinkling pathnames throughout ** your other modules' source code: **jsa("lzstring", "js/lz-string.js"); ** ** Optional headready define, if you want it, uncomment the next line: **define("headready", 1); ** ** Add low priority CSS files here. ** High priority CSS should use direct <link> entries instead if you ** do not need to fulfill a custom dependency for those files. ** CSS files you need to fulfill dependency 'id' for, must use scss(id, url) ** instead. ** **var t="//cdn.remixml.org/css/"; **css(t+"blue.css", "bluecssloaded"); // CSS fulfilling dependency **css(t+"sample.css"); // Low prio CSS ** ** Add medium priority Javascript files here. ** Typically jQuery should be loaded here, if needed: ** **require(["domready"], ()=> { ** js("//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"); **}); ** ** Executed when the DOM has been loaded completely. ** Typically the place to add remaining low priority Javascript files. ** High priority Javascript files should use direct script entries instead. ** If you do not use jQuery, take out the jQuery dependency from the line ** below: */ require(["domready", "jQuery"], (domready)=> { /*var t="//cdn.remixml.org/js/"; **js(t+"sequentialload.js"); // Legacy sequential low prio loads **js(t+"sequentialload2.js"); // Legacy sequential low prio loads **js(t+"sequentialload3.js"); // Legacy sequential low prio loads **js("lastjs.js"); // Fullfill lastjs dependency after ** // all js()s have been processed **js(t+"asynchronousload.js", "async"); // Low priority async */ setTimeout(()=> { /* ** Low priority non-interactive */ js("//www.googletagmanager.com/gtm.js?id=GTM-xxxxxx", "async", 1); }, 2048); /* ** Call domready(1) with a one as argument once from the startup scripts. ** Call domready() without arguments from your SPA after that on every ** page refresh. Calling domready() before domready(1) has been called ** will silently ignore the domready() call. ** You can offer a limited scope for the domready() call by supplying ** an argument as in domready(scope). The argument will be available ** to the scripts being run. If you do not provide an argument, they ** will receive $(document) (the jQuery whole document object/scope). */ domready(1); }); /* ** This is where your config area ends. Do not edit until after the ** end of the script */ /* Cut BEGIN for lockandload_trailer.inc */ // // Use the "jQuery" dependency instead of "jquery" to avoid a race // for an undefined W.$ // E("jQuery", ["jquery"], ($, i)=> { W.jQuery=W.$=$; while (i=E.Q.shift()) $(i); return $; }); // // Non-global require() // require.undef(n) to unload a module prior to reloading it // require.load(p, obj) to load a javascript file on demand // asynchronously, with an optional obj describing extra attributes. // E(F, ["module"], (R)=> (W[F].undef=(n)=>R[n]=0, W[F].load=(p,y)=>js(P[p]||p, 1, 0, y), W[F])); // // Define "domready" dependency, it also returns the factory for running // the $$(...) scheduled functions: run it in the SPA after page switches. // W.onload=()=>E("domready", ["module"], (R)=> (t,i)=> { if(E.S[0]||t==1) { t=!(t==1?E.S.shift():t)&&R.jquery?$(D):t; for (i=0; i<E.S.length; E.S[i++](t)); }}); })(window,document,"require",define,{}); </script> <!-- Cut END for lockandload_trailer.inc --> <!-- The preceding <script> *must* stay at the end of the <head> --> </head> <body> <h1>Minimalist AMD-compliant Javascript and CSS loader</h1> <p>Your glorious content</p> </body> </html>