ajaxify 8.2.9 → 8.3.0

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.
Files changed (3) hide show
  1. package/ajaxify.js +774 -569
  2. package/ajaxify.min.js +1 -1
  3. package/package.json +2 -2
package/ajaxify.js CHANGED
@@ -5,9 +5,9 @@
5
5
  *
6
6
  * Copyright Arvind Gupta; MIT Licensed
7
7
  *
8
- * Version 8.2.9
8
+ * Version 8.3.0
9
9
  */
10
-
10
+
11
11
  /* INTERFACE: See also https://4nf.org/interface/
12
12
 
13
13
  Simplest plugin call:
@@ -19,30 +19,38 @@ Ajaxifies the whole site, dynamically replacing the elements specified in "eleme
19
19
 
20
20
  let Ay; //to become the global handle for the main Ajaxify parent class - if used by you already, please rename and rebuild
21
21
 
22
- function _won(a, b, c = false) { if(c === false) c = {once: true}; setTimeout( () => window.addEventListener(a, b, c) ); };
22
+ function _won(a, b, c = false) {
23
+ if (c === false) c = { once: true };
24
+ setTimeout(() => window.addEventListener(a, b, c));
25
+ }
23
26
 
24
27
  //Module global helpers
25
- let rootUrl = location.origin, inlineclass = "ajy-inline",
28
+ let rootUrl = location.origin,
29
+ inlineclass = "ajy-inline",
26
30
  bdy,
27
- qa=(s,o=document)=>o.querySelectorAll(s),
28
- qs=(s,o=document)=>o.querySelector(s),
29
- qha=(e)=>qs("head").appendChild(e),
30
- prC=(e)=>e.parentNode.removeChild(e),
31
- dcE=(e)=>document.createElement(e),
32
-
33
- _copyAttributes=(el, S, flush)=>{ //copy all attributes of element generically
34
- if(flush) [...el.attributes].forEach(e => el.removeAttribute(e.name)); //delete all old attributes
35
- [...S.attributes].forEach(e => e.nodeValue == "ajy-body" || el.setAttribute(e.nodeName, e.nodeValue)); //low-level insertion
36
- };
31
+ qa = (s, o = document) => o.querySelectorAll(s),
32
+ qs = (s, o = document) => o.querySelector(s),
33
+ qha = (e) => qs("head").appendChild(e),
34
+ qba = (e) => qs("body").appendChild(e),
35
+ prC = (e) => e.parentNode.removeChild(e),
36
+ dcE = (e) => document.createElement(e),
37
+ _copyAttributes = (el, S, flush) => {
38
+ //copy all attributes of element generically
39
+ if (flush) [...el.attributes].forEach((e) => el.removeAttribute(e.name)); //delete all old attributes
40
+ [...S.attributes].forEach((e) => e.nodeValue == "ajy-body" || el.setAttribute(e.nodeName, e.nodeValue)); //low-level insertion
41
+ };
37
42
 
38
43
  // The main plugin - Ajaxify
39
- // Is passed the global options
44
+ // Is passed the global options
40
45
  // Checks for necessary pre-conditions - otherwise gracefully degrades
41
46
  // Initialises sub-plugins
42
47
  // Calls Pronto
43
- class Ajaxify { constructor(options) {
44
- String.prototype.iO = function(s) { return this.toString().indexOf(s) + 1; }; //Intuitively better understandable shorthand for String.indexOf() - String.iO()
45
- Ay = this;
48
+ class Ajaxify {
49
+ constructor(options) {
50
+ String.prototype.iO = function (s) {
51
+ return this.toString().indexOf(s) + 1;
52
+ }; //Intuitively better understandable shorthand for String.indexOf() - String.iO()
53
+ Ay = this;
46
54
 
47
55
  //Options default values
48
56
  Ay.s = {
@@ -76,512 +84,614 @@ Ay.s = {
76
84
  memoryoff : false, // strings - separated by ", " - if matched in any URLs - only these are NOT executed - set to "true" to disable memory completely
77
85
  cb : 0, // callback handler on completion of each Ajax request - default 0
78
86
  pluginon : true, // Plugin set "on" or "off" (==false) manually
79
- passCount: false // Show number of pass for debugging
87
+ passCount: false, // Show number of pass for debugging
88
+ DCLDelay: 0
80
89
  };
81
90
 
82
91
 
83
- Ay.pass = 0; Ay.currentURL = ""; Ay.h = {};
84
- Ay.parse = (s, pl) => (pl = dcE('div'), pl.insertAdjacentHTML('afterbegin', s), pl.firstElementChild); // HTML parser
85
- Ay.trigger = (t, e) => { let ev = document.createEvent('HTMLEvents'); ev.initEvent("pronto." + t, true, false); ev.data = e ? e : Ay.Rq("e"); window.dispatchEvent(ev); };
86
- Ay.internal = (url) => { if (!url) return false; if (typeof(url) === "object") url = url.href; if (url==="") return true; return url.substring(0,rootUrl.length) === rootUrl || !url.iO(":"); };
87
- Ay.intevents = () => {
88
- let iFn = function (a, b, c = false) { if ((this === document || this === window) && a=="DOMContentLoaded") setTimeout(b); else this.ael(a,b,c);}; // if "DOMContentLoaded" - execute function, else - add event listener
89
- EventTarget.prototype.ael = EventTarget.prototype.addEventListener; // store original method
90
- EventTarget.prototype.addEventListener = iFn; // start intercepting event listener addition
91
- };
92
-
93
- function _on(eventName, elementSelector, handler, el = document) { //e.currentTarget is document when the handler is called
94
- el.addEventListener(eventName, function(e) {
95
- // loop parent nodes from the target to the delegation node
96
- for (var target = e.target; target && target != this; target = target.parentNode) {
97
- if (target.matches(elementSelector)) {
98
- handler(target, e);
99
- break;
92
+ Ay.pass = 0;
93
+ Ay.currentURL = "";
94
+ Ay.h = {};
95
+ Ay.parse = (s, pl) => ((pl = dcE("div")), pl.insertAdjacentHTML("afterbegin", s), pl.firstElementChild); // HTML parser
96
+
97
+ // Trigger event
98
+ Ay.triggerEvent = (v) => {
99
+ if (Ay.s.DCLDelay !== false) {
100
+ const evnt = new Event(v, { bubbles: true, cancelable: true });
101
+ const dw = v === "DOMContentLoaded" ? document : window;
102
+ Ay.s.DCLDelay === 0
103
+ ? dw.dispatchEvent(evnt)
104
+ : setTimeout(() => {
105
+ dw.dispatchEvent(evnt);
106
+ }, Ay.s.DCLDelay);
100
107
  }
108
+ };
109
+
110
+ Ay.trigger = (t, e) => {
111
+ const ev = new Event("pronto." + t, { bubbles: true, cancelable: false });
112
+ ev.data = e ? e : Ay.Rq("e");
113
+ window.dispatchEvent(ev);
114
+ };
115
+
116
+ Ay.internal = (url) => {
117
+ if (!url) return false;
118
+ if (typeof url === "object") url = url.href;
119
+ if (url === "") return true;
120
+ return url.substring(0, rootUrl.length) === rootUrl || !url.iO(":");
121
+ };
122
+
123
+ Ay.intevents = () => {
124
+ let iFn = function (a, b, c = false) {
125
+ // if "DOMContentLoaded" - execute function, else - add event listener
126
+ if ((this === document || this === window) && (a == "DOMContentLoaded" || a == "load")) {
127
+ c = c ? Object.assign(c, { once: true }) : { once: true };
128
+ }
129
+ return this && this.ael(a, b, c);
130
+ };
131
+ EventTarget.prototype.ael = EventTarget.prototype.addEventListener; // store original method
132
+ EventTarget.prototype.addEventListener = iFn; // start intercepting event listener addition
133
+ };
134
+
135
+ function _on(eventName, elementSelector, handler, el = document) {
136
+ //e.currentTarget is document when the handler is called
137
+ el.addEventListener(
138
+ eventName,
139
+ function (e) {
140
+ // loop parent nodes from the target to the delegation node
141
+ for (var target = e.target; target && target != this; target = target.parentNode) {
142
+ if (target.matches(elementSelector)) {
143
+ handler(target, e);
144
+ break;
145
+ }
146
+ }
147
+ },
148
+ !!eventName.iO("mo")
149
+ );
101
150
  }
102
- }, !!eventName.iO('mo'));
103
- }
104
-
105
- class Hints { constructor(h) { let _ = this;
106
- _.list = (typeof h === 'string' && h.length > 0) ? h.split(", ") : false; //hints are passed as a comma separated string
107
- _.find = (t) => (!t || !_.list) ? false : _.list.some(h => t.iO(h)); //iterate through hints within passed text (t)
108
- }}
109
-
110
- function lg(m){ Ay.s.verbosity && console && console.log(m); }
111
-
112
- // The GetPage class
113
- // First parameter (o) is a switch:
114
- // empty - returns cache
115
- // <URL> - loads HTML via Ajax, second parameter "p" must be callback
116
- // + - pre-fetches page, second parameter "p" must be URL, third parameter "p2" must be callback
117
- // - - loads page into DOM and handle scripts, second parameter "p" must hold selection to load
118
- // x - returns response
119
- // otherwise - returns selection of current page to client
120
-
121
- class GetPage { constructor() {
122
- let rsp = 0, cb = 0, plus = 0, rt = "", ct = 0, rc = 0, ac = 0,
123
-
124
- //Regexes for escaping fetched HTML of a whole page - best of Baluptons Ajaxify
125
- //for html, head and body tag
126
- //Makes it possible to pre-fetch an entire page
127
- docType = /<\!DOCTYPE[^>]*>/i,
128
- tagso = /<(html|head)([\s\>])/gi,
129
- tagsod = /<(body)([\s\>])/gi,
130
- tagsc = /<\/(html|head|body)\>/gi,
131
-
132
- //Helper strings
133
- div12 = '<div class="ajy-$1"$2',
134
- divid12 = '<div id="ajy-$1"$2';
135
-
136
- this.a = function (o, p, p2) {
137
- if (!o) return Ay.cache.g();
138
-
139
- if (o.iO("/")) {
140
- cb = p;
141
- if(plus == o) return;
142
- return _lPage(o);
143
- }
144
-
145
- if (o === "+") {
146
- plus = p;
147
- cb = p2;
148
- return _lPage(p, true);
149
- }
150
-
151
- if (o === "a") { if (rc > 0) {_cl(); ac.abort();} return; }
152
- if (o === "s") return ((rc) ? 1 : 0) + rt;
153
- if (o === "-") return _lSel(p);
154
- if (o === "x") return rsp;
155
-
156
- if (!Ay.cache.g()) return;
157
- if (o === "body") return qs("#ajy-" + o, Ay.cache.g());
158
- if (o === "script") return qa(o, Ay.cache.g());
159
151
 
160
- return qs((o === "title") ? o : ".ajy-" + o, Ay.cache.g());
161
- };
162
- let _lSel = t => (
163
- Ay.pass++,
164
- _lEls(t),
165
- qa("body > script").forEach(e => (e.classList.contains(inlineclass)) ? prC(e) : false),
166
- Ay.scripts.t(),
167
- Ay.scripts.s(),
168
- Ay.scripts.c()
169
- ),
170
- _lPage = (h, pre) => {
171
- if (h.iO("#")) h = h.split("#")[0];
172
- if (Ay.Rq("is") || !Ay.cache.l(h)) return _lAjax(h, pre);
173
-
174
- plus = 0;
175
- if (cb) return cb();
176
- },
177
- _ld = (t, h) => {
178
- if(!h) return; //no input
179
-
180
- var c = h.cloneNode(true); // clone element node (true = deep clone)
181
- qa("script", c).forEach(e => prC(e));
182
- _copyAttributes(t, c, true);
183
- t.innerHTML = c.innerHTML;
184
- },
185
- _lEls = t =>
186
- Ay.cache.g() && !_isBody(t) && t.forEach(function(e) {
187
- _ld(e, qs("#" + e.getAttribute("id"), Ay.cache.g()));
188
- }),
189
- _isBody = t => t[0].tagName.toLowerCase() == "body" && (_ld(bdy, qs("#ajy-body", Ay.cache.g())), 1),
190
- _lAjax = (hin, pre) => {
191
- var ispost = Ay.Rq("is");
192
- if (pre) rt="p"; else rt="c";
193
-
194
- ac = new AbortController(); // set abort controller
195
- rc++; // set active request counter
196
- fetch(hin, {
197
- method: ((ispost) ? "POST" : "GET"),
198
- cache: "default",
199
- mode: "same-origin",
200
- headers: {"X-Requested-With": "XMLHttpRequest"},
201
- body: (ispost) ? Ay.Rq("d") : null,
202
- signal: ac.signal
203
- }).then(r => {
204
- if (!r.ok || !_isHtml(r)) {
205
- if (!pre) {location.href = hin;}
206
- return;
152
+ class Hints {
153
+ constructor(h) {
154
+ let _ = this;
155
+ _.list = typeof h === "string" && h.length > 0 ? h.split(", ") : false; //hints are passed as a comma separated string
156
+ _.find = (t) => (!t || !_.list ? false : _.list.some((h) => t.iO(h))); //iterate through hints within passed text (t)
207
157
  }
208
- rsp = r; // store response
209
- return r.text();
210
- }).then(r => {
211
- _cl(1); // clear only plus variable
212
- if (!r) return; // ensure data
213
- rsp.responseText = r; // store response text
214
-
215
- return _cache(hin, r);
216
- }).catch(err => {
217
- if(err.name === "AbortError") return;
218
- try {
219
- Ay.trigger("error", err);
220
- lg("Response text : " + err.message);
221
- return _cache(hin, err.message, err);
222
- } catch (e) {}
223
- }).finally(() => rc--); // reset active request counter
224
- },
225
- _cl = c => (plus = 0, (!c) ? cb = 0 : 0), // clear plus AND/OR callback
226
- _cache = (href, h, err) => Ay.cache.s(Ay.parse(_parseHTML(h))) && (Ay.pages.p([href, Ay.cache.g()]), 1) && cb && cb(err),
227
- _isHtml = x => (ct = x.headers.get("content-type")) && (ct.iO("html") || ct.iO("form-")),
228
- _parseHTML = h => dcE("html").innerHTML = _replD(h).trim(),
229
- _replD = h => String(h).replace(docType, "").replace(tagso, div12).replace(tagsod, divid12).replace(tagsc, "</div>")
230
- }}
231
-
232
- // The Rq plugin - stands for request
233
- // Stores all kinds of and manages data concerning the pending request
234
- // Simplifies the Pronto plugin by managing request data separately, instead of passing it around...
235
- // Second parameter (p) : data
236
- // First parameter (o) values:
237
- // = - check whether internally stored "href" ("h") variable is the same as the global currentURL
238
- // ! - update last request ("l") variable with passed href
239
- // ? - Edin's intelligent plausibility check - can spawn an external fetch abort
240
- // v - validate value passed in "p", which is expected to be a click event value - also performs "i" afterwards
241
- // i - initialise request defaults and return "c" (currentTarget)
242
- // h - access internal href hard
243
- // e - set / get internal "e" (event)
244
- // p - set / get internal "p" (push flag)
245
- // is - set / get internal "ispost" (flag whether request is a POST)
246
- // d - set / get internal "d" (data for central fetch())
247
- // C - set / get internal "can" ("href" of canonical URL)
248
- // c - check whether simple canonical URL is given and return, otherwise return value passed in "p"
249
- class RQ { constructor() {
250
- let ispost = 0, data = 0, push = 0, can = 0, e = 0, c = 0, h = 0, l = false;
251
-
252
- this.a = function (o, p, t) {
253
- if(o === "=") {
254
- if(p) return h === Ay.currentURL //check whether internally stored "href" ("h") variable is the same as the global currentURL
255
- || h === l; //or href of last request ("l")
256
- return h === Ay.currentURL; //for click requests
257
158
  }
258
159
 
259
- if(o === "!") return l = h; //store href in "l" (last request)
260
-
261
- if(o === "?") { //Edin previously called this "isOK" - powerful intelligent plausibility check
262
- let xs=Ay.fn("s");
263
- if (!xs.iO("0") && !p) Ay.fn("a"); //if fetch is not idle and new request is standard one, do ac.abort() to set it free
264
- if (xs==="1c" && p) return false; //if fetch is processing standard request and new request is prefetch, cancel prefetch until fetch is finished
265
- if (xs==="1p" && p) Ay.s.memoryoff ? Ay.fn("a") : 1; //if fetch is processing prefetch request and new request is prefetch do nothing (see [options] comment below)
266
- //([semaphore options for requests] Ay.fn("a") -> abort previous, proceed with new | return false -> leave previous, stop new | return true -> proceed)
267
- return true;
160
+ function lg(m) {
161
+ Ay.s.verbosity && console && console.log(m);
268
162
  }
269
163
 
270
- if(o === "v") { //validate value passed in "p", which is expected to be a click event value - also performs "i" afterwards
271
- if(!p) return false; //ensure data
272
- _setE(p, t); //Set event and href in one go
273
- if(!Ay.internal(h)) return false; //if not internal -> report failure
274
- o = "i"; //continue with "i"
275
- }
276
-
277
- if(o === "i") { //initialise request defaults and return "c" (currentTarget)
278
- ispost = false; //GET assumed
279
- data = null; //reset data
280
- push = true; //assume we want to push URL to the History API
281
- can = false; //reset can (canonical URL)
282
- return h; //return "h" (href)
283
- }
284
-
285
- if(o === "h") { // Access href hard
286
- if(p) {
287
- if (typeof p === "string") e = 0; // Reset e -> default handler
288
- h = (p.href) ? p.href : p; // Poke in href hard
164
+ // The GetPage class
165
+ // First parameter (o) is a switch:
166
+ // empty - returns cache
167
+ // <URL> - loads HTML via Ajax, second parameter "p" must be callback
168
+ // + - pre-fetches page, second parameter "p" must be URL, third parameter "p2" must be callback
169
+ // - - loads page into DOM and handle scripts, second parameter "p" must hold selection to load
170
+ // x - returns response
171
+ // otherwise - returns selection of current page to client
172
+
173
+ class GetPage {
174
+ constructor() {
175
+ let rsp = 0,
176
+ cb = 0,
177
+ plus = 0,
178
+ rt = "",
179
+ ct = 0,
180
+ rc = 0,
181
+ ac = 0,
182
+ //Regexes for escaping fetched HTML of a whole page - best of Baluptons Ajaxify
183
+ //for html, head and body tag
184
+ //Makes it possible to pre-fetch an entire page
185
+ docType = /<\!DOCTYPE[^>]*>/i,
186
+ tagso = /<(html|head)([\s\>])/gi,
187
+ tagsod = /<(body)([\s\>])/gi,
188
+ tagsc = /<\/(html|head|body)\>/gi,
189
+ //Helper strings
190
+ div12 = '<div class="ajy-$1"$2',
191
+ divid12 = '<div id="ajy-$1"$2';
192
+
193
+ this.a = function (o, p, p2) {
194
+ if (!o) return Ay.cache.g();
195
+
196
+ if (o.iO("/")) {
197
+ cb = p;
198
+ if (plus == o) return;
199
+ return _lPage(o);
200
+ }
201
+
202
+ if (o === "+") {
203
+ plus = p;
204
+ cb = p2;
205
+ return _lPage(p, true);
206
+ }
207
+
208
+ if (o === "a") {
209
+ if (rc > 0) {
210
+ _cl();
211
+ ac.abort();
212
+ }
213
+ return;
214
+ }
215
+ if (o === "s") return (rc ? 1 : 0) + rt;
216
+ if (o === "-") return _lSel(p);
217
+ if (o === "x") return rsp;
218
+
219
+ if (!Ay.cache.g()) return;
220
+ if (o === "body") return qs("#ajy-" + o, Ay.cache.g());
221
+ if (o === "script") return qa(o, Ay.cache.g());
222
+
223
+ return qs(o === "title" ? o : ".ajy-" + o, Ay.cache.g());
224
+ };
225
+ let _lSel = (t) => (Ay.pass++, _lEls(t), qa("body > script").forEach((e) => (e.classList.contains(inlineclass) ? prC(e) : false)), Ay.scripts.t(), Ay.scripts.s(), Ay.scripts.c()),
226
+ _lPage = (h, pre) => {
227
+ if (h.iO("#")) h = h.split("#")[0];
228
+ if (Ay.Rq("is") || !Ay.cache.l(h)) return _lAjax(h, pre);
229
+
230
+ plus = 0;
231
+ if (cb) return cb();
232
+ },
233
+ _ld = (t, h) => {
234
+ if (!h) return; //no input
235
+
236
+ var c = h.cloneNode(true); // clone element node (true = deep clone)
237
+ qa("script", c).forEach((e) => prC(e));
238
+ _copyAttributes(t, c, true);
239
+ t.innerHTML = c.innerHTML;
240
+ },
241
+ _lEls = (t) =>
242
+ Ay.cache.g() &&
243
+ !_isBody(t) &&
244
+ t.forEach(function (e) {
245
+ _ld(e, qs("#" + e.getAttribute("id"), Ay.cache.g()));
246
+ }),
247
+ _isBody = (t) => t[0].tagName.toLowerCase() == "body" && (_ld(bdy, qs("#ajy-body", Ay.cache.g())), 1),
248
+ _lAjax = (hin, pre) => {
249
+ var ispost = Ay.Rq("is");
250
+ if (pre) rt = "p";
251
+ else rt = "c";
252
+
253
+ ac = new AbortController(); // set abort controller
254
+ rc++; // set active request counter
255
+ fetch(hin, {
256
+ method: ispost ? "POST" : "GET",
257
+ cache: "default",
258
+ mode: "same-origin",
259
+ headers: { "X-Requested-With": "XMLHttpRequest" },
260
+ body: ispost ? Ay.Rq("d") : null,
261
+ signal: ac.signal,
262
+ })
263
+ .then((r) => {
264
+ if (!r.ok || !_isHtml(r)) {
265
+ if (!pre) {
266
+ location.href = hin;
267
+ }
268
+ return;
269
+ }
270
+ rsp = r; // store response
271
+ return r.text();
272
+ })
273
+ .then((r) => {
274
+ _cl(1); // clear only plus variable
275
+ if (!r) return; // ensure data
276
+ rsp.responseText = r; // store response text
277
+
278
+ return _cache(hin, r);
279
+ })
280
+ .catch((err) => {
281
+ if (err.name === "AbortError") return;
282
+ try {
283
+ Ay.trigger("error", err);
284
+ lg("Response text : " + err.message);
285
+ return _cache(hin, err.message, err);
286
+ } catch (e) { }
287
+ })
288
+ .finally(() => rc--); // reset active request counter
289
+ },
290
+ _cl = (c) => ((plus = 0), !c ? (cb = 0) : 0), // clear plus AND/OR callback
291
+ _cache = (href, h, err) => Ay.cache.s(Ay.parse(_parseHTML(h))) && (Ay.pages.p([href, Ay.cache.g()]), 1) && cb && cb(err),
292
+ _isHtml = (x) => (ct = x.headers.get("content-type")) && (ct.iO("html") || ct.iO("form-")),
293
+ _parseHTML = (h) => (dcE("html").innerHTML = _replD(h).trim()),
294
+ _replD = (h) => String(h).replace(docType, "").replace(tagso, div12).replace(tagsod, divid12).replace(tagsc, "</div>");
289
295
  }
290
-
291
- return h; //href
292
- }
293
-
294
- if(o === "e") { //set / get internal "e" (event)
295
- if(p) _setE(p, t); //Set event and href in one go
296
- return e ? e : h; // Return "e" or if not given "h"
297
- }
298
-
299
- if(o === "p") { //set / get internal "p" (push flag)
300
- if(p !== undefined) push = p;
301
- return push;
302
296
  }
303
297
 
304
- if(o === "is") { //set / get internal "ispost" (flag whether request is a POST)
305
- if(p !== undefined) ispost = p;
306
- return ispost;
307
- }
308
-
309
- if(o === "d") { //set / get internal "d" (data for central fetch())
310
- if(p) data = p;
311
- return data;
312
- }
313
-
314
- if(o === "C") { //set internal "can" ("href" of canonical URL)
315
- if(p !== undefined) can = p;
316
- return can;
317
- }
318
-
319
- if(o === "c") return can && can !== p && !p.iO("#") && !p.iO("?") ? can : p; //get internal "can" ("href" of canonical URL)
320
- };
321
- let _setE = (p, t) => h = typeof (e = p) !== "string" ? (e.currentTarget && e.currentTarget.href) || (t && t.href) || e.currentTarget.action || e.originalEvent.state.url : e
322
- }}
323
-
324
- // The Frms plugin - stands for forms
325
- // Ajaxify all forms in the specified divs
326
- // Switch (o) values:
327
- // d - set divs variable
328
- // a - Ajaxify all forms in divs
329
- class Frms { constructor() {
330
- let fm = 0, divs = 0;
331
-
332
- this.a = function (o, p) {
333
- if (!Ay.s.forms || !o) return; //ensure data
334
-
335
- if(o === "d") divs = p; //set divs variable
336
- if(o === "a") divs.forEach(div => { //iterate through divs
337
- Array.prototype.filter.call(qa(Ay.s.forms, div), function(e) { //filter forms
338
- let c = e.getAttribute("action");
339
- return(Ay.internal(c && c.length > 0 ? c : Ay.currentURL)); //ensure "action"
340
- }).forEach(frm => { //iterate through forms
341
- frm.addEventListener("submit", q => { //create event listener
342
- fm = q.target; // fetch target
343
-
344
- p = _k(); //Serialise data
345
- var g = "get", //assume GET
346
- m = fm.getAttribute("method"); //fetch method attribute
347
- if (m.length > 0 && m.toLowerCase() == "post") g = "post"; //Override with "post"
348
-
349
- var h, a = fm.getAttribute("action"); //fetch action attribute
350
- if (a && a.length > 0) h = a; //found -> store
351
- else h = Ay.currentURL; //not found -> select current URL
352
-
353
- Ay.Rq("v", q); //validate request
354
-
355
- if (g == "get") h = _b(h, p); //GET -> copy URL parameters
356
- else {
357
- Ay.Rq("is", true); //set is POST in request data
358
- Ay.Rq("d", p); //save data in request data
298
+ // The Rq plugin - stands for request
299
+ // Stores all kinds of and manages data concerning the pending request
300
+ // Simplifies the Pronto plugin by managing request data separately, instead of passing it around...
301
+ // Second parameter (p) : data
302
+ // First parameter (o) values:
303
+ // = - check whether internally stored "href" ("h") variable is the same as the global currentURL
304
+ // ! - update last request ("l") variable with passed href
305
+ // ? - Edin's intelligent plausibility check - can spawn an external fetch abort
306
+ // v - validate value passed in "p", which is expected to be a click event value - also performs "i" afterwards
307
+ // i - initialise request defaults and return "c" (currentTarget)
308
+ // h - access internal href hard
309
+ // e - set / get internal "e" (event)
310
+ // p - set / get internal "p" (push flag)
311
+ // is - set / get internal "ispost" (flag whether request is a POST)
312
+ // d - set / get internal "d" (data for central fetch())
313
+ // C - set / get internal "can" ("href" of canonical URL)
314
+ // c - check whether simple canonical URL is given and return, otherwise return value passed in "p"
315
+ class RQ {
316
+ constructor() {
317
+ let ispost = 0,
318
+ data = 0,
319
+ push = 0,
320
+ can = 0,
321
+ e = 0,
322
+ c = 0,
323
+ h = 0,
324
+ l = false;
325
+
326
+ this.a = function (o, p, t) {
327
+ if (o === "=") {
328
+ if (p)
329
+ return (
330
+ h === Ay.currentURL || //check whether internally stored "href" ("h") variable is the same as the global currentURL
331
+ h === l
332
+ ); //or href of last request ("l")
333
+ return h === Ay.currentURL; //for click requests
334
+ }
335
+
336
+ if (o === "!") return (l = h); //store href in "l" (last request)
337
+
338
+ if (o === "?") {
339
+ //Edin previously called this "isOK" - powerful intelligent plausibility check
340
+ let xs = Ay.fn("s");
341
+ if (!xs.iO("0") && !p) Ay.fn("a"); //if fetch is not idle and new request is standard one, do ac.abort() to set it free
342
+ if (xs === "1c" && p) return false; //if fetch is processing standard request and new request is prefetch, cancel prefetch until fetch is finished
343
+ if (xs === "1p" && p) Ay.s.memoryoff ? Ay.fn("a") : 1; //if fetch is processing prefetch request and new request is prefetch do nothing (see [options] comment below)
344
+ //([semaphore options for requests] Ay.fn("a") -> abort previous, proceed with new | return false -> leave previous, stop new | return true -> proceed)
345
+ return true;
346
+ }
347
+
348
+ if (o === "v") {
349
+ //validate value passed in "p", which is expected to be a click event value - also performs "i" afterwards
350
+ if (!p) return false; //ensure data
351
+ _setE(p, t); //Set event and href in one go
352
+ if (!Ay.internal(h)) return false; //if not internal -> report failure
353
+ o = "i"; //continue with "i"
354
+ }
355
+
356
+ if (o === "i") {
357
+ //initialise request defaults and return "c" (currentTarget)
358
+ ispost = false; //GET assumed
359
+ data = null; //reset data
360
+ push = true; //assume we want to push URL to the History API
361
+ can = false; //reset can (canonical URL)
362
+ return h; //return "h" (href)
363
+ }
364
+
365
+ if (o === "h") {
366
+ // Access href hard
367
+ if (p) {
368
+ if (typeof p === "string") e = 0; // Reset e -> default handler
369
+ h = p.href ? p.href : p; // Poke in href hard
370
+ }
371
+
372
+ return h; //href
373
+ }
374
+
375
+ if (o === "e") {
376
+ //set / get internal "e" (event)
377
+ if (p) _setE(p, t); //Set event and href in one go
378
+ return e ? e : h; // Return "e" or if not given "h"
379
+ }
380
+
381
+ if (o === "p") {
382
+ //set / get internal "p" (push flag)
383
+ if (p !== undefined) push = p;
384
+ return push;
385
+ }
386
+
387
+ if (o === "is") {
388
+ //set / get internal "ispost" (flag whether request is a POST)
389
+ if (p !== undefined) ispost = p;
390
+ return ispost;
391
+ }
392
+
393
+ if (o === "d") {
394
+ //set / get internal "d" (data for central fetch())
395
+ if (p) data = p;
396
+ return data;
397
+ }
398
+
399
+ if (o === "C") {
400
+ //set internal "can" ("href" of canonical URL)
401
+ if (p !== undefined) can = p;
402
+ return can;
403
+ }
404
+
405
+ if (o === "c") return can && can !== p && !p.iO("#") && !p.iO("?") ? can : p; //get internal "can" ("href" of canonical URL)
406
+ };
407
+ let _setE = (p, t) => (h = typeof (e = p) !== "string" ? (e.currentTarget && e.currentTarget.href) || (t && t.href) || e.currentTarget.action || e.originalEvent.state.url : e);
359
408
  }
360
-
361
- Ay.trigger("submit", h); //raise pronto.submit event
362
- Ay.pronto(0, { href: h }); //programmatically change page
363
-
364
- q.preventDefault(); //prevent default form action
365
- return(false); //success -> disable default behaviour
366
- });
367
- });
368
- });
369
- };
370
- let _k = () => {
371
- let o = new FormData(fm), n = qs("input[name][type=submit]", fm);
372
-
373
- if (n) o.append(n.getAttribute("name"), n.value);
374
- return o;
375
- },
376
- _b = (m, n) => {
377
- let s = "";
378
- if (m.iO("?")) m = m.substring(0, m.iO("?"));
379
-
380
- for (var [k, v] of n.entries()) s += `${k}=${encodeURIComponent(v)}&`;
381
- return `${m}?${s.slice(0,-1)}`;
382
- }
383
- }}
384
-
385
- // The Pronto plugin - Pronto variant of Ben Plum's Pronto plugin - low level event handling in general
386
- // Works on a selection, passed to Pronto by the selection, which specifies, which elements to Ajaxify
387
- // Switch (h) values:
388
- // i - initialise Pronto
389
- // <object> - fetch href part and continue with _request()
390
- // <URL> - set "h" variable of Rq hard and continue with _request()
391
- class Pronto { constructor() {
392
- let gsl = 0, requestTimer = 0, pd = 150, ptim = 0;
393
- Ay.h.prefetchoff = new Hints(Ay.s.prefetchoff);
394
-
395
- this.a = function (sl, h) {
396
- if(!h) return; //ensure data
397
-
398
- if(h === "i") { //request to initialise
399
- bdy = document.body;
400
- if(!sl.length) sl = "body";
401
- gsl = qa(sl); //copy selection to global selector
402
- Ay.frms = new Frms().a; //initialise forms sub-plugin
403
- if(Ay.s.idleTime) Ay.slides = new classSlides(Ay).a; //initialise optional slideshow sub-plugin
404
- Ay.scrolly = new Scrolly(); //initialise scroll effects sub-plugin
405
- (Ay.offsets = new Offsets()).f();
406
- Ay.hApi = new HApi();
407
- _init_p(); //initialise Pronto sub-plugin
408
- return sl; //return query selector for chaining
409
409
  }
410
410
 
411
- if(typeof(h) === "object") { //jump to internal page programmatically -> handler for forms sub-plugin
412
- Ay.Rq("h", h);
413
- _request();
414
- return;
411
+ // The Frms plugin - stands for forms
412
+ // Ajaxify all forms in the specified divs
413
+ // Switch (o) values:
414
+ // d - set divs variable
415
+ // a - Ajaxify all forms in divs
416
+ class Frms {
417
+ constructor() {
418
+ let fm = 0,
419
+ divs = 0;
420
+
421
+ this.a = function (o, p) {
422
+ if (!Ay.s.forms || !o) return; //ensure data
423
+
424
+ if (o === "d") divs = p; //set divs variable
425
+ if (o === "a")
426
+ divs.forEach((div) => {
427
+ //iterate through divs
428
+ Array.prototype.filter
429
+ .call(qa(Ay.s.forms, div), function (e) {
430
+ //filter forms
431
+ let c = e.getAttribute("action");
432
+ return Ay.internal(c && c.length > 0 ? c : Ay.currentURL); //ensure "action"
433
+ })
434
+ .forEach((frm) => {
435
+ //iterate through forms
436
+ frm.addEventListener("submit", (q) => {
437
+ //create event listener
438
+ fm = q.target; // fetch target
439
+
440
+ p = _k(); //Serialise data
441
+ var g = "get", //assume GET
442
+ m = fm.getAttribute("method"); //fetch method attribute
443
+ if (m.length > 0 && m.toLowerCase() == "post") g = "post"; //Override with "post"
444
+
445
+ var h,
446
+ a = fm.getAttribute("action"); //fetch action attribute
447
+ if (a && a.length > 0) h = a; //found -> store
448
+ else h = Ay.currentURL; //not found -> select current URL
449
+
450
+ Ay.Rq("v", q); //validate request
451
+
452
+ if (g == "get") h = _b(h, p); //GET -> copy URL parameters
453
+ else {
454
+ Ay.Rq("is", true); //set is POST in request data
455
+ Ay.Rq("d", p); //save data in request data
456
+ }
457
+
458
+ Ay.trigger("submit", h); //raise pronto.submit event
459
+ Ay.pronto(0, { href: h }); //programmatically change page
460
+
461
+ q.preventDefault(); //prevent default form action
462
+ return false; //success -> disable default behaviour
463
+ });
464
+ });
465
+ });
466
+ };
467
+ let _k = () => {
468
+ let o = new FormData(fm),
469
+ n = qs("input[name][type=submit]", fm);
470
+
471
+ if (n) o.append(n.getAttribute("name"), n.value);
472
+ return o;
473
+ },
474
+ _b = (m, n) => {
475
+ let s = "";
476
+ if (m.iO("?")) m = m.substring(0, m.iO("?"));
477
+
478
+ for (var [k, v] of n.entries()) s += `${k}=${encodeURIComponent(v)}&`;
479
+ return `${m}?${s.slice(0, -1)}`;
480
+ };
481
+ }
415
482
  }
416
483
 
417
- if(h.iO("/")) { //jump to internal page programmatically -> default handler
418
- Ay.Rq("h", h);
419
- _request(true);
420
- }
421
- };
422
- let _init_p = () => {
423
- Ay.hApi.r(window.location.href);
424
- window.addEventListener("popstate", _onPop);
425
- if (Ay.s.prefetchoff !== true) {
426
- _on("mouseenter", Ay.s.selector, _preftime); // start prefetch timeout
427
- _on("mouseleave", Ay.s.selector, _prefstop); // stop prefetch timeout
428
- _on("touchstart", Ay.s.selector, _prefetch);
429
- }
430
- _on("click", Ay.s.selector, _click, bdy);
431
- Ay.frms("d", qa("body"));
432
- Ay.frms("a");
433
- Ay.frms("d", gsl);
434
- if(Ay.s.idleTime) Ay.slides("i");
435
- },
436
- _preftime = (t, e) => (_prefstop(), ptim = setTimeout(()=> _prefetch(t, e), pd)), // call prefetch if timeout expires without being cleared by _prefstop
437
- _prefstop = () => clearTimeout(ptim),
438
- _prefetch = (t, e) => {
439
- if(Ay.s.prefetchoff === true) return;
440
- if (!Ay.Rq("?", true)) return;
441
- var href = Ay.Rq("v", e, t);
442
- if (Ay.Rq("=", true) || !href || Ay.h.prefetchoff.find(href)) return;
443
- Ay.fn("+", href, () => false);
444
- },
445
- _stopBubbling = e => (
446
- e.preventDefault(),
447
- e.stopPropagation(),
448
- e.stopImmediatePropagation()
449
- ),
450
- _click = (t, e, notPush) => {
451
- if(!Ay.Rq("?")) return;
452
- var href = Ay.Rq("v", e, t);
453
- if(!href || _exoticKey(t)) return;
454
- if(href.substr(-1) ==="#") return true;
455
- if(_hashChange()) {
456
- Ay.hApi.r(href);
457
- return true;
484
+ // The Pronto plugin - Pronto variant of Ben Plum's Pronto plugin - low level event handling in general
485
+ // Works on a selection, passed to Pronto by the selection, which specifies, which elements to Ajaxify
486
+ // Switch (h) values:
487
+ // i - initialise Pronto
488
+ // <object> - fetch href part and continue with _request()
489
+ // <URL> - set "h" variable of Rq hard and continue with _request()
490
+ class Pronto {
491
+ constructor() {
492
+ let gsl = 0,
493
+ requestTimer = 0,
494
+ pd = 150,
495
+ ptim = 0;
496
+ Ay.h.prefetchoff = new Hints(Ay.s.prefetchoff);
497
+
498
+ this.a = function (sl, h) {
499
+ if (!h) return; //ensure data
500
+
501
+ if (h === "i") {
502
+ //request to initialise
503
+ bdy = document.body;
504
+ if (!sl.length) sl = "body";
505
+ gsl = qa(sl); //copy selection to global selector
506
+ Ay.frms = new Frms().a; //initialise forms sub-plugin
507
+ if (Ay.s.idleTime) Ay.slides = new classSlides(Ay).a; //initialise optional slideshow sub-plugin
508
+ Ay.scrolly = new Scrolly(); //initialise scroll effects sub-plugin
509
+ (Ay.offsets = new Offsets()).f();
510
+ Ay.hApi = new HApi();
511
+ _init_p(); //initialise Pronto sub-plugin
512
+ return sl; //return query selector for chaining
513
+ }
514
+
515
+ if (typeof h === "object") {
516
+ //jump to internal page programmatically -> handler for forms sub-plugin
517
+ Ay.Rq("h", h);
518
+ _request();
519
+ return;
520
+ }
521
+
522
+ if (h.iO("/")) {
523
+ //jump to internal page programmatically -> default handler
524
+ Ay.Rq("h", h);
525
+ _request(true);
526
+ }
527
+ };
528
+ let _init_p = () => {
529
+ Ay.hApi.r(window.location.href);
530
+ window.addEventListener("popstate", _onPop);
531
+ if (Ay.s.prefetchoff !== true) {
532
+ _on("mouseenter", Ay.s.selector, _preftime); // start prefetch timeout
533
+ _on("mouseleave", Ay.s.selector, _prefstop); // stop prefetch timeout
534
+ _on("touchstart", Ay.s.selector, _prefetch);
535
+ }
536
+ _on("click", Ay.s.selector, _click, bdy);
537
+ Ay.frms("d", qa("body"));
538
+ Ay.frms("a");
539
+ Ay.frms("d", gsl);
540
+ if (Ay.s.idleTime) Ay.slides("i");
541
+ },
542
+ _preftime = (t, e) => (_prefstop(), (ptim = setTimeout(() => _prefetch(t, e), pd))), // call prefetch if timeout expires without being cleared by _prefstop
543
+ _prefstop = () => clearTimeout(ptim),
544
+ _prefetch = (t, e) => {
545
+ if (Ay.s.prefetchoff === true) return;
546
+ if (!Ay.Rq("?", true)) return;
547
+ var href = Ay.Rq("v", e, t);
548
+ if (Ay.Rq("=", true) || !href || Ay.h.prefetchoff.find(href)) return;
549
+ Ay.fn("+", href, () => false);
550
+ },
551
+ _stopBubbling = (e) => (e.preventDefault(), e.stopPropagation(), e.stopImmediatePropagation()),
552
+ _click = (t, e, notPush) => {
553
+ if (!Ay.Rq("?")) return;
554
+ var href = Ay.Rq("v", e, t);
555
+ if (!href || _exoticKey(t)) return;
556
+ if (href.substr(-1) === "#") return true;
557
+ if (_hashChange()) {
558
+ Ay.hApi.r(href);
559
+ return true;
560
+ }
561
+
562
+ Ay.scrolly.p();
563
+ _stopBubbling(e);
564
+ if (Ay.Rq("=")) Ay.hApi.r();
565
+ if (Ay.s.refresh || !Ay.Rq("=")) _request(notPush);
566
+ },
567
+ _request = (notPush) => {
568
+ Ay.Rq("!");
569
+ if (notPush) Ay.Rq("p", false);
570
+ Ay.fn(Ay.Rq("h"), (err) => {
571
+ if (err) {
572
+ lg("Error in _request : " + err);
573
+ Ay.trigger("error", err);
574
+ }
575
+ _render();
576
+ });
577
+ },
578
+ _render = () => {
579
+ if (Ay.s.requestDelay) {
580
+ if (requestTimer) clearTimeout(requestTimer);
581
+ requestTimer = setTimeout(_doRender, Ay.s.requestDelay);
582
+ } else _doRender();
583
+ },
584
+ _onPop = (e) => {
585
+ var url = window.location.href;
586
+
587
+ Ay.Rq("i");
588
+ Ay.Rq("h", url);
589
+ Ay.Rq("p", false);
590
+ Ay.scrolly.p();
591
+
592
+ if (!url || url === Ay.currentURL) return;
593
+ Ay.fn(url, _render);
594
+ },
595
+ _doRender = () => {
596
+ if (Ay.s.bodyClasses) _copyAttributes(bdy, Ay.fn("body"), true);
597
+
598
+ var href = Ay.Rq("h"),
599
+ title;
600
+ href = Ay.Rq("c", href);
601
+
602
+ if (Ay.Rq("p")) Ay.hApi.p(href);
603
+ else Ay.hApi.r(href);
604
+ if ((title = Ay.fn("title"))) qs("title").innerHTML = title.innerHTML;
605
+ Ay.Rq("C", Ay.fn("-", gsl));
606
+ Ay.frms("a");
607
+
608
+ Ay.scrolly.l();
609
+ _gaCaptureView(href);
610
+ Ay.triggerEvent("DOMContentLoaded");
611
+ if (Ay.s.passCount) qs("#" + Ay.s.passCount).innerHTML = "Pass: " + Ay.pass;
612
+ if (Ay.s.cb) Ay.s.cb();
613
+ },
614
+ _gaCaptureView = (href) => {
615
+ href = "/" + href.replace(rootUrl, "");
616
+ if (typeof window.ga !== "undefined") window.ga("send", "pageview", href);
617
+ else if (typeof window._gaq !== "undefined") window._gaq.push(["_trackPageview", href]);
618
+ },
619
+ _exoticKey = (t) => {
620
+ var href = Ay.Rq("h"),
621
+ e = Ay.Rq("e"),
622
+ tgt = e.currentTarget.target || t.target;
623
+ return e.which > 1 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || tgt === "_blank" || href.iO("wp-login") || href.iO("wp-admin");
624
+ },
625
+ _hashChange = () => {
626
+ var e = Ay.Rq("e");
627
+ return (e.hash && e.href.replace(e.hash, "") === window.location.href.replace(location.hash, "")) || e.href === window.location.href + "#";
628
+ };
629
+ }
458
630
  }
459
631
 
460
- Ay.scrolly.p();
461
- _stopBubbling(e);
462
- if(Ay.Rq("=")) Ay.hApi.r();
463
- if(Ay.s.refresh || !Ay.Rq("=")) _request(notPush);
464
- },
465
- _request = notPush => {
466
- Ay.Rq("!");
467
- if(notPush) Ay.Rq("p", false);
468
- Ay.trigger("request");
469
- Ay.fn(Ay.Rq("h"), err => {
470
- if (err) {
471
- lg("Error in _request : " + err);
472
- Ay.trigger("error", err);
632
+ Ay.init = () => {
633
+ let o = options;
634
+ if (!o || typeof o !== "string") {
635
+ if (document.readyState === "complete" || (document.readyState !== "loading" && !document.documentElement.doScroll)) run();
636
+ else document.addEventListener("DOMContentLoaded", run);
637
+ return Ay;
638
+ } else return Ay.pronto(0, o);
639
+ };
640
+
641
+ let run = () => {
642
+ Ay.s = Object.assign(Ay.s, options);
643
+ (Ay.pages = new Pages()).f();
644
+ Ay.pronto = new Pronto().a;
645
+ if (load()) {
646
+ Ay.pronto(Ay.s.elements, "i");
647
+ if (Ay.s.deltas) Ay.scripts.o();
473
648
  }
649
+ },
650
+ load = () => {
651
+ if (!(window.history && window.history.pushState && window.history.replaceState) || !Ay.s.pluginon) {
652
+ lg("Gracefully exiting...");
653
+ return false;
654
+ }
474
655
 
475
- _render();
476
- });
477
- },
478
- _render = () => {
479
- Ay.trigger("beforeload");
480
- if(Ay.s.requestDelay) {
481
- if(requestTimer) clearTimeout(requestTimer);
482
- requestTimer = setTimeout(_doRender, Ay.s.requestDelay);
483
- } else _doRender();
484
- },
485
- _onPop = e => {
486
- var url = window.location.href;
487
-
488
- Ay.Rq("i");
489
- Ay.Rq("h", url);
490
- Ay.Rq("p", false);
491
- Ay.scrolly.p();
492
-
493
- if (!url || url === Ay.currentURL) return;
494
- Ay.trigger("request");
495
- Ay.fn(url, _render);
496
- },
497
- _doRender = () => {
498
- Ay.trigger("load");
499
- if(Ay.s.bodyClasses) _copyAttributes(bdy, Ay.fn("body"), true);
500
-
501
- var href = Ay.Rq("h"), title;
502
- href = Ay.Rq("c", href);
503
-
504
- if(Ay.Rq("p")) Ay.hApi.p(href); else Ay.hApi.r(href);
505
- if(title = Ay.fn("title")) qs("title").innerHTML = title.innerHTML;
506
- Ay.Rq("C", Ay.fn("-", gsl));
507
- Ay.frms("a");
508
-
509
- Ay.scrolly.l();
510
- _gaCaptureView(href);
511
- Ay.trigger("render");
512
- if(Ay.s.passCount) qs("#" + Ay.s.passCount).innerHTML = "Pass: " + Ay.pass;
513
- if(Ay.s.cb) Ay.s.cb();
514
- },
515
- _gaCaptureView = href => {
516
- href = "/" + href.replace(rootUrl,"");
517
- if (typeof window.ga !== "undefined") window.ga("send", "pageview", href);
518
- else if (typeof window._gaq !== "undefined") window._gaq.push(["_trackPageview", href]);
519
- },
520
- _exoticKey = (t) => {
521
- var href = Ay.Rq("h"), e = Ay.Rq("e"), tgt = e.currentTarget.target || t.target;
522
- return (e.which > 1 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || tgt === "_blank"
523
- || href.iO("wp-login") || href.iO("wp-admin"));
524
- },
525
- _hashChange = () => {
526
- var e = Ay.Rq("e");
527
- return (e.hash && e.href.replace(e.hash, "") === window.location.href.replace(location.hash, "") || e.href === window.location.href + "#");
528
- }
529
- }}
530
-
531
-
532
- Ay.init = () => {
533
- let o = options;
534
- if (!o || typeof(o) !== "string") {
535
- if (document.readyState === "complete" ||
536
- (document.readyState !== "loading" && !document.documentElement.doScroll)) run();
537
- else document.addEventListener('DOMContentLoaded', run);
538
- return Ay;
539
- }
540
- else return Ay.pronto(0, o);
541
- };
542
-
543
- let run = () => {
544
- Ay.s = Object.assign(Ay.s, options);
545
- (Ay.pages = new Pages()).f();
546
- Ay.pronto = new Pronto().a;
547
- if (load()) {
548
- Ay.pronto(Ay.s.elements, "i");
549
- if (Ay.s.deltas) Ay.scripts.o();
550
- }
551
- },
552
- load = () => {
553
- if (!(window.history && window.history.pushState && window.history.replaceState) || !Ay.s.pluginon) {
554
- lg("Gracefully exiting...");
555
- return false;
556
- }
557
-
558
- lg("Ajaxify loaded..."); //verbosity option steers, whether this initialisation message is output
559
-
656
+ lg("Ajaxify loaded..."); //verbosity option steers, whether this initialisation message is output
657
+
658
+ Ay.scripts = new Scrpts();
659
+ Ay.h.inlinehints = new Hints(Ay.s.inlinehints);
660
+ Ay.h.inlineskip = new Hints(Ay.s.inlineskip);
661
+ Ay.cache = new Cache();
662
+ Ay.memory = new Memory();
663
+ Ay.h.memoryoff = new Hints(Ay.s.memoryoff);
664
+ Ay.fn = Ay.getPage = new GetPage().a;
665
+ Ay.detScripts = new DetScripts();
666
+ Ay.addAll = new AddAll();
667
+ Ay.h.alwayshints = new Hints(Ay.s.alwayshints);
668
+ Ay.Rq = new RQ().a;
669
+ return true;
670
+ };
560
671
  if (Ay.s.intevents) Ay.intevents(); // intercept events
561
- Ay.scripts = new Scrpts(); Ay.h.inlinehints = new Hints(Ay.s.inlinehints); Ay.h.inlineskip = new Hints(Ay.s.inlineskip);
562
- Ay.cache = new Cache();
563
- Ay.memory = new Memory(); Ay.h.memoryoff = new Hints(Ay.s.memoryoff);
564
- Ay.fn = Ay.getPage = new GetPage().a;
565
- Ay.detScripts = new DetScripts();
566
- Ay.addAll = new AddAll(); Ay.h.alwayshints = new Hints(Ay.s.alwayshints);
567
- Ay.Rq = new RQ().a;
568
- return true;
569
- };
570
- Ay.init(); // initialize Ajaxify on definition
571
- }}
672
+ Ay.init(); // initialize Ajaxify on definition
673
+ }
674
+ }
572
675
 
573
676
  // The stateful Cache class
574
677
  // this.d = entire current page (as an object)
575
678
  class Cache {
576
- g(){ return this.d } //getter
577
- s(v){ return this.d = v } //setter
578
- l(u){ let v = Ay.memory.l(u); return this.s(v === false ? v : Ay.pages.l(v)) } //lookup URL and load
679
+ g() {
680
+ return this.d;
681
+ } //getter
682
+ s(v) {
683
+ return (this.d = v);
684
+ } //setter
685
+ l(u) {
686
+ let v = Ay.memory.l(u);
687
+ return this.s(v === false ? v : Ay.pages.l(v));
688
+ } //lookup URL and load
579
689
  }
580
690
 
581
691
  // The stateful Memory class
582
692
  // Usage: Ay.memory.l(<URL>) - returns the same URL if not turned off internally
583
693
  class Memory {
584
- l(h){
694
+ l(h) {
585
695
  if (!h || Ay.s.memoryoff === true) return false;
586
696
  if (Ay.s.memoryoff === false) return h;
587
697
  return Ay.h.memoryoff.find(h) ? false : h;
@@ -591,56 +701,82 @@ class Memory {
591
701
  // The stateful Pages class
592
702
  // this.d = Array of pages - [0] = URL // [1] = reference to whole page
593
703
  class Pages {
594
- f(){ this.d = [] } //flush
595
- l(u){ if (this.P(u)) return this.d[this.i][1] } //lookup URL and return page
596
- p(o){ if(this.P(o[0])) this.d[this.i]=o; else this.d.push(o) } //update or push page passed as an object
597
- P(u){ return (this.i = this.d.findIndex(e => e[0] == u)) + 1 } //lookup page index and store in "i"
704
+ f() {
705
+ this.d = [];
706
+ } //flush
707
+ l(u) {
708
+ if (this.P(u)) return this.d[this.i][1];
709
+ } //lookup URL and return page
710
+ p(o) {
711
+ if (this.P(o[0])) this.d[this.i] = o;
712
+ else this.d.push(o);
713
+ } //update or push page passed as an object
714
+ P(u) {
715
+ return (this.i = this.d.findIndex((e) => e[0] == u)) + 1;
716
+ } //lookup page index and store in "i"
598
717
  }
599
718
 
600
719
  // The DetScripts class - stands for "detach scripts"
601
720
  // Works on "s" <object> that is passed in and fills it
602
- class DetScripts {
721
+ class DetScripts {
603
722
  d(s) {
604
- if(!(this.h = Ay.pass ? Ay.fn("head") : qs("head"))) return true; //If pass is 0 -> fetch head from DOM, otherwise from target page
723
+ if (!(this.h = Ay.pass ? Ay.fn("head") : qs("head"))) return true; //If pass is 0 -> fetch head from DOM, otherwise from target page
605
724
  this.lk = qa("link", this.h); // Fetch links from DOM
606
725
  s.j = Ay.pass ? Ay.fn("script") : qa("script"); //If pass is 0 -> fetch JSs from DOM, otherwise from target page
607
726
  s.c = this.x("stylesheet"); //Extract stylesheets
608
727
  s.y = qa("style", this.h); //Extract style tags
609
728
  s.can = this.x("canonical"); //Extract canonical tag
610
729
  }
611
- x(v){ return Array.prototype.filter.call(this.lk, e => e.getAttribute("rel").iO(v)) } //Extract link tags with given "rel"
730
+ x(v) {
731
+ return Array.prototype.filter.call(this.lk, (e) => e.getAttribute("rel").iO(v));
732
+ } //Extract link tags with given "rel"
612
733
  }
613
734
 
614
735
  // The Offsets class
615
736
  // this.d = Array of pages - [0] = URL // [1] = offset
616
737
  class Offsets {
617
- f(){ this.d = [] } //flush internal offsets array - must be performed by parent
618
- l(h){ if(h.iO("?")) h = h.split("?")[0]; //lookup page offset
738
+ f() {
739
+ this.d = [];
740
+ } //flush internal offsets array - must be performed by parent
741
+ l(h) {
742
+ if (h.iO("?")) h = h.split("?")[0]; //lookup page offset
619
743
  return this.O(h) ? this.d[this.i][1] : 0; //return if found otherwise 0
620
744
  }
621
- p(h){ let us1 = h.iO("?") ? h.split("?")[0] : h, //initialise all helper variables in one go
622
- us = us1.iO("#") ? us1.split("#")[0] : us1,
623
- os = [us, (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop];
624
- if(this.O(us)) this.d[this.i]=os; else this.d.push(os); // update if found, otherwise push
745
+ p(h) {
746
+ let us1 = h.iO("?") ? h.split("?")[0] : h, //initialise all helper variables in one go
747
+ us = us1.iO("#") ? us1.split("#")[0] : us1,
748
+ os = [us, (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop];
749
+ if (this.O(us)) this.d[this.i] = os;
750
+ else this.d.push(os); // update if found, otherwise push
625
751
  }
626
- O(h){ return (this.i = this.d.findIndex(e => e[0] == h)) + 1 } //find URL in internal array - add 1 for convenience
752
+ O(h) {
753
+ return (this.i = this.d.findIndex((e) => e[0] == h)) + 1;
754
+ } //find URL in internal array - add 1 for convenience
627
755
  }
628
756
 
629
757
  // The Scrolly class
630
758
  // operates on Ay.currentURL
631
- class Scrolly { constructor() { if ('scrollRestoration' in history) history.scrollRestoration = 'manual' }
632
- p(){ Ay.s.scrolltop == "s" && Ay.offsets.p(Ay.currentURL) }
633
- l(){ let o = Ay.currentURL;
634
- if(o.iO("#") && (o.iO("#") < o.length - 1)) { //if hash in URL and not standalone hash
759
+ class Scrolly {
760
+ constructor() {
761
+ if ("scrollRestoration" in history) history.scrollRestoration = "manual";
762
+ }
763
+ p() {
764
+ Ay.s.scrolltop == "s" && Ay.offsets.p(Ay.currentURL);
765
+ }
766
+ l() {
767
+ let o = Ay.currentURL;
768
+ if (o.iO("#") && o.iO("#") < o.length - 1) {
769
+ //if hash in URL and not standalone hash
635
770
  let el = qs("#" + o.split("#")[1]); //fetch the element
636
- if(!el) return; //nothing found -> return quickly
771
+ if (!el) return; //nothing found -> return quickly
637
772
  let box = el.getBoundingClientRect();
638
773
  return this.s(box.top + window.pageYOffset - document.documentElement.clientTop); // ...animate to ID
639
774
  }
640
- if(Ay.s.scrolltop == "s") this.s(Ay.offsets.l(o)); //smart scroll -> lookup and restore offset
775
+ if (Ay.s.scrolltop == "s") this.s(Ay.offsets.l(o)); //smart scroll -> lookup and restore offset
641
776
  else Ay.s.scrolltop && this.s(0); //scrolltop true -> scroll to top of page
642
777
  }
643
- s(o){ if(Ay.s.scrollDelay === false) window.scrollTo(0, o); //scroll to offset
778
+ s(o) {
779
+ if (Ay.s.scrollDelay === false) window.scrollTo(0, o); //scroll to offset
644
780
  else setTimeout(() => window.scrollTo(0, o), Ay.s.scrollDelay);
645
781
  }
646
782
  }
@@ -648,34 +784,54 @@ class Scrolly { constructor() { if ('scrollRestoration' in history) history.scro
648
784
  // The HAPi class
649
785
  // operates on Ay.currentURL - manages operations on the History API centrally(replaceState / pushState)
650
786
  class HApi {
651
- r(h){ let c = this.u(h); history.replaceState({ url: c }, "state-" + c, c); } //perform replaceState
652
- p(h){ let c = this.u(h); if (c !== window.location.href) history.pushState({ url: c }, "state-" + c, c); } //perform pushState
653
- u(h){ if(h) Ay.currentURL = h; return Ay.currentURL; } //update currentURL if given and return always
787
+ r(h) {
788
+ let c = this.u(h);
789
+ history.replaceState({ url: c }, "state-" + c, c);
790
+ } //perform replaceState
791
+ p(h) {
792
+ let c = this.u(h);
793
+ if (c !== window.location.href) history.pushState({ url: c }, "state-" + c, c);
794
+ } //perform pushState
795
+ u(h) {
796
+ if (h) Ay.currentURL = h;
797
+ return Ay.currentURL;
798
+ } //update currentURL if given and return always
654
799
  }
655
800
 
656
801
  // The AddAll class
657
- // Works on a new selection of scripts to apply delta-loading to it
658
- class AddAll { constructor() { this.CSS = []; this.JS = []; }
659
- a(sl, pk) { //only public function
660
- if(!sl.length || Ay.s.deltas === "n") return; //ensure input and that delta-loading is enabled
802
+ // Works on a new selection of scripts to apply delta-loading to it
803
+ class AddAll {
804
+ constructor() {
805
+ this.CSS = [];
806
+ this.JS = [];
807
+ this.TCS = [];
808
+ }
809
+ a(sl, pk) {
810
+ //only public function
811
+ this.TCS = [];
812
+ if (!sl.length || Ay.s.deltas === "n") return; //ensure input and that delta-loading is enabled
661
813
 
662
814
  this.PK = pk; //Copy "primary key" into internal variable
663
815
 
664
- if(!Ay.s.deltas) return sl.forEach(e => this.iScript(e)); //process all scripts and return quickly
816
+ if (!Ay.s.deltas) return sl.forEach((e) => this.iScript(e)); //process all scripts and return quickly
665
817
  //deltas presumed to be "true" -> proceed with normal delta-loading
666
818
 
667
819
  this.O = pk == "href" ? this.CSS : this.JS; //Load old stylesheets or JS
668
820
 
669
- sl.forEach(t => { //Iterate through selection
821
+ sl.forEach((t) => {
822
+ //Iterate through selection
670
823
  let url = this.gA(t); //fetch URL
671
- if(!Ay.pass) return url && this.O.push(url); //Fill new array on initial load, nothing more
672
- if(t.getAttribute("data-class") == "always" || Ay.h.alwayshints.find(url)) { //Class always handling
824
+ if (!Ay.pass) return url && this.O.push(url); //Fill new array on initial load, nothing more
825
+ if (t.getAttribute("data-class") == "always" || Ay.h.alwayshints.find(url)) {
826
+ //Class always handling
673
827
  this.removeScript(); //remove from DOM
674
828
  this.iScript(t); //insert back single external script in the head
675
829
  return;
676
830
  }
677
- if(url) { //URL?
678
- if(!this.O.some(e => e == url)) { // Test, whether new
831
+ if (url) {
832
+ //URL?
833
+ if (!this.O.some((e) => e == url)) {
834
+ // Test, whether new
679
835
  this.O.push(url); //If yes: Push to old array
680
836
  this.iScript(t);
681
837
  }
@@ -683,62 +839,111 @@ class AddAll { constructor() { this.CSS = []; this.JS = []; }
683
839
  return;
684
840
  }
685
841
 
686
- if(pk != "href" && !t.classList.contains("no-ajaxy")) Ay.scripts.i(t); //Inline JS script? -> inject into DOM
842
+ if (pk != "href" && !t.classList.contains("no-ajaxy")) Ay.scripts.i(t); //Inline JS script? -> inject into DOM
687
843
  });
688
- }
689
- // Fetch full url of link or script tag
690
- gA(e){ return this.u = e[this.PK]; }
691
-
692
- iScript(S){
844
+ // Wait for all the scripts to be loaded and then trigger loaded
845
+ "src" === pk &&
846
+ Promise.all(this.TCS)
847
+ .then(() => { })
848
+ .catch((l) => { })
849
+ .finally(() => Ay.triggerEvent("load"));
850
+ }
851
+ // Fetch full url of link or script tag
852
+ gA(e) {
853
+ return (this.u = e[this.PK]);
854
+ }
855
+ //Append script to the DOM
856
+ appendScript(S) {
857
+ return new Promise((resolve, reject) => {
858
+ var sc = dcE("script");
859
+ //wait for the load event
860
+ sc.onload = () => resolve();
861
+ sc.onreadystatechange = () => resolve();
862
+ sc.onerror = (event) => reject(event);
863
+ // If the script has defer then it will set it defer otherwise async
864
+ sc.async = S.hasAttribute("defer") ? false : Ay.s.asyncdef;
865
+ _copyAttributes(sc, S);
866
+ qba(sc);
867
+ });
868
+ }
869
+ iScript(S) {
693
870
  this.gA(S);
694
- if(this.PK == "href") return qha(Ay.parse('<link rel="stylesheet" type="text/css" href="*" />'.replace("*", this.u)));
695
- if(!this.u) return Ay.scripts.i(S);
696
-
697
- var sc = dcE("script");
698
- sc.async = Ay.s.asyncdef;
699
- _copyAttributes(sc, S);
700
- qha(sc);
871
+ if (this.PK == "href") return qha(Ay.parse('<link rel="stylesheet" type="text/css" href="*" />'.replace("*", this.u)));
872
+ if (!this.u) return Ay.scripts.i(S);
873
+ //Push the promises to be resolved
874
+ this.TCS.push(this.appendScript(S));
875
+ }
876
+ removeScript() {
877
+ qa((this.PK == "href" ? 'link[href*="!"]' : 'script[src*="!"]').replace("!", this.u.substring(this.u.lastIndexOf("/") + 1))).forEach((e) => prC(e));
701
878
  }
702
- removeScript(){ qa((this.PK == "href" ? 'link[href*="!"]' : 'script[src*="!"]').replace("!", this.u)).forEach(e => prC(e)) }
703
879
  }
704
880
 
705
881
  // The stateful Scrpts plugin
706
- class Scrpts { constructor(){ this.S = {} }
707
- s(){ this.allstyle(this.S.y) } //all style tags
708
- o(){ this.d(); this.a() } //on initial load
709
- c(){ return Ay.s.canonical && this.S.can ? this.S.can.getAttribute("href") : false } //canonical href
710
- d(){ return Ay.detScripts.d(this.S) } //detach scripts - returning true indicates an error
711
- i(o){ this.one(o) } //inline script -> o is scripts object
712
- t(){ this.d() || this.a() } //former "true" / default method - detach and delta load
713
- a(){ this.delta(this.S) } //delta loading core
714
-
715
- allstyle(S){
716
- !Ay.s.style || !S || (
717
- qa("style", qs("head")).forEach(e => prC(e)),
718
- S.forEach(el => {
719
- let st = Ay.parse('<style>' + el.textContent + '</style>');
720
- _copyAttributes(st, el);
721
- qha(st); //append to the head
722
- })
723
- )
882
+ class Scrpts {
883
+ constructor() {
884
+ this.S = {};
724
885
  }
725
- one(S){
726
- (!(this.x = S.textContent).iO("new Ajaxify(") &&
727
- ((Ay.s.inline && !Ay.h.inlineskip.find(this.x)) || S.classList.contains("ajaxy") ||
728
- Ay.h.inlinehints.find(this.x))
729
- ) && this.add(S)
886
+ s() {
887
+ this.allstyle(this.S.y);
888
+ } //all style tags
889
+ o() {
890
+ this.d();
891
+ this.a();
892
+ } //on initial load
893
+ c() {
894
+ return Ay.s.canonical && this.S.can ? this.S.can.getAttribute("href") : false;
895
+ } //canonical href
896
+ d() {
897
+ return Ay.detScripts.d(this.S);
898
+ } //detach scripts - returning true indicates an error
899
+ i(o) {
900
+ this.one(o);
901
+ } //inline script -> o is scripts object
902
+ t() {
903
+ this.d() || this.a();
904
+ } //former "true" / default method - detach and delta load
905
+ a() {
906
+ this.delta(this.S);
907
+ } //delta loading core
908
+
909
+ allstyle(S) {
910
+ !Ay.s.style ||
911
+ !S ||
912
+ (qa("style", qs("head")).forEach((e) => prC(e)),
913
+ S.forEach((el) => {
914
+ let st = Ay.parse("<style>" + el.textContent + "</style>");
915
+ _copyAttributes(st, el);
916
+ qha(st); //append to the head
917
+ }));
730
918
  }
731
- add(S){
732
- if(!this.x || !this.x.length) return;
733
- if(Ay.s.inlineappend || (S.getAttribute("type") && !S.getAttribute("type").iO("text/javascript"))) try { return this.app(S); } catch (e) { }
919
+ one(S) {
920
+ !(this.x = S.textContent).iO("new Ajaxify(") && ((Ay.s.inline && !Ay.h.inlineskip.find(this.x)) || S.classList.contains("ajaxy") || Ay.h.inlinehints.find(this.x)) && this.add(S);
921
+ }
922
+ add(S) {
923
+ if (!this.x || !this.x.length) return;
924
+ if (Ay.s.inlineappend || (S.getAttribute("type") && !S.getAttribute("type").iO("text/javascript")))
925
+ try {
926
+ return this.app(S);
927
+ } catch (e) { }
734
928
 
735
- try { eval(this.x) } catch (e1) {
929
+ try {
930
+ eval(this.x);
931
+ } catch (e1) {
736
932
  lg("Error in inline script : " + this.x + "\nError code : " + e1);
737
933
  }
738
934
  }
739
- app(S){ let sc = dcE("script"); _copyAttributes(sc, S); sc.classList.add(inlineclass);
740
- try {sc.appendChild(document.createTextNode(this.x))} catch(e) {sc.text = this.x}
935
+ app(S) {
936
+ let sc = dcE("script");
937
+ _copyAttributes(sc, S);
938
+ sc.classList.add(inlineclass);
939
+ try {
940
+ sc.appendChild(document.createTextNode(this.x));
941
+ } catch (e) {
942
+ sc.text = this.x;
943
+ }
741
944
  return qs("body").appendChild(sc);
742
945
  }
743
- delta(S){ Ay.addAll.a(S.c, "href"), Ay.addAll.a(S.j, "src") }
946
+ delta(S) {
947
+ Ay.addAll.a(S.c, "href"), Ay.addAll.a(S.j, "src");
948
+ }
744
949
  }