@hotwired/turbo 7.1.0 → 7.2.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/turbo.es2017-esm.js +1139 -630
- package/dist/turbo.es2017-umd.js +1153 -637
- package/dist/types/core/bardo.d.ts +7 -2
- package/dist/types/core/cache.d.ts +10 -0
- package/dist/types/core/drive/error_renderer.d.ts +2 -1
- package/dist/types/core/drive/form_submission.d.ts +12 -5
- package/dist/types/core/drive/head_snapshot.d.ts +3 -3
- package/dist/types/core/drive/history.d.ts +1 -1
- package/dist/types/core/drive/navigator.d.ts +5 -4
- package/dist/types/core/drive/page_renderer.d.ts +11 -5
- package/dist/types/core/drive/page_view.d.ts +8 -5
- package/dist/types/core/drive/preloader.d.ts +14 -0
- package/dist/types/core/drive/progress_bar.d.ts +1 -0
- package/dist/types/core/drive/visit.d.ts +17 -5
- package/dist/types/core/frames/frame_controller.d.ts +50 -24
- package/dist/types/core/frames/frame_redirector.d.ts +12 -10
- package/dist/types/core/frames/frame_renderer.d.ts +8 -1
- package/dist/types/core/frames/frame_view.d.ts +2 -1
- package/dist/types/core/index.d.ts +12 -4
- package/dist/types/core/native/adapter.d.ts +3 -2
- package/dist/types/core/native/browser_adapter.d.ts +18 -9
- package/dist/types/core/renderer.d.ts +11 -5
- package/dist/types/core/session.d.ts +81 -21
- package/dist/types/core/snapshot.d.ts +5 -2
- package/dist/types/core/streams/stream_actions.d.ts +4 -2
- package/dist/types/core/streams/stream_message.d.ts +2 -6
- package/dist/types/core/streams/stream_message_renderer.d.ts +7 -0
- package/dist/types/core/types.d.ts +4 -0
- package/dist/types/core/view.d.ts +13 -7
- package/dist/types/elements/frame_element.d.ts +10 -6
- package/dist/types/elements/index.d.ts +1 -0
- package/dist/types/elements/stream_element.d.ts +8 -1
- package/dist/types/elements/stream_source_element.d.ts +7 -0
- package/dist/types/http/fetch_request.d.ts +11 -3
- package/dist/types/http/index.d.ts +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/observers/cache_observer.d.ts +1 -1
- package/dist/types/observers/form_link_click_observer.d.ts +14 -0
- package/dist/types/observers/form_submit_observer.d.ts +2 -1
- package/dist/types/observers/link_click_observer.d.ts +5 -4
- package/dist/types/polyfills/submit-event.d.ts +1 -7
- package/dist/types/tests/functional/async_script_tests.d.ts +1 -6
- package/dist/types/tests/functional/autofocus_tests.d.ts +1 -9
- package/dist/types/tests/functional/cache_observer_tests.d.ts +1 -5
- package/dist/types/tests/functional/drive_custom_body_tests.d.ts +1 -0
- package/dist/types/tests/functional/drive_disabled_tests.d.ts +1 -9
- package/dist/types/tests/functional/drive_tests.d.ts +1 -8
- package/dist/types/tests/functional/form_mode_tests.d.ts +1 -0
- package/dist/types/tests/functional/form_submission_tests.d.ts +1 -84
- package/dist/types/tests/functional/frame_navigation_tests.d.ts +1 -7
- package/dist/types/tests/functional/frame_tests.d.ts +1 -52
- package/dist/types/tests/functional/import_tests.d.ts +1 -4
- package/dist/types/tests/functional/loading_tests.d.ts +1 -13
- package/dist/types/tests/functional/navigation_tests.d.ts +1 -38
- package/dist/types/tests/functional/pausable_rendering_tests.d.ts +1 -6
- package/dist/types/tests/functional/pausable_requests_tests.d.ts +1 -6
- package/dist/types/tests/functional/preloader_tests.d.ts +1 -0
- package/dist/types/tests/functional/rendering_tests.d.ts +1 -35
- package/dist/types/tests/functional/scroll_restoration_tests.d.ts +1 -6
- package/dist/types/tests/functional/stream_tests.d.ts +1 -6
- package/dist/types/tests/functional/visit_tests.d.ts +1 -15
- package/dist/types/tests/helpers/page.d.ts +50 -0
- package/dist/types/tests/unit/deprecated_adapter_support_test.d.ts +10 -10
- package/dist/types/util.d.ts +14 -3
- package/package.json +23 -9
- package/CHANGELOG.md +0 -3
- package/dist/types/core/frames/form_interceptor.d.ts +0 -12
- package/dist/types/core/frames/link_interceptor.d.ts +0 -16
- package/dist/types/tests/functional/index.d.ts +0 -17
- package/dist/types/tests/helpers/functional_test_case.d.ts +0 -44
- package/dist/types/tests/helpers/remote_channel.d.ts +0 -10
- package/dist/types/tests/helpers/turbo_drive_test_case.d.ts +0 -21
package/dist/turbo.es2017-umd.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Turbo 7.
|
|
3
|
-
Copyright ©
|
|
2
|
+
Turbo 7.2.0-rc.1
|
|
3
|
+
Copyright © 2022 Basecamp, LLC
|
|
4
4
|
*/
|
|
5
5
|
(function (global, factory) {
|
|
6
6
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
7
7
|
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
8
8
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Turbo = {}));
|
|
9
|
-
}(this, (function (exports) { 'use strict';
|
|
9
|
+
})(this, (function (exports) { 'use strict';
|
|
10
10
|
|
|
11
11
|
(function () {
|
|
12
|
-
if (window.Reflect === undefined ||
|
|
12
|
+
if (window.Reflect === undefined ||
|
|
13
|
+
window.customElements === undefined ||
|
|
13
14
|
window.customElements.polyfillWrapFlushCallback) {
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
17
|
const BuiltInHTMLElement = HTMLElement;
|
|
17
18
|
const wrapperForTheName = {
|
|
18
|
-
|
|
19
|
+
HTMLElement: function HTMLElement() {
|
|
19
20
|
return Reflect.construct(BuiltInHTMLElement, [], this.constructor);
|
|
20
|
-
}
|
|
21
|
+
},
|
|
21
22
|
};
|
|
22
|
-
window.HTMLElement =
|
|
23
|
-
wrapperForTheName['HTMLElement'];
|
|
23
|
+
window.HTMLElement = wrapperForTheName["HTMLElement"];
|
|
24
24
|
HTMLElement.prototype = BuiltInHTMLElement.prototype;
|
|
25
25
|
HTMLElement.prototype.constructor = HTMLElement;
|
|
26
26
|
Object.setPrototypeOf(HTMLElement, BuiltInHTMLElement);
|
|
@@ -78,7 +78,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
78
78
|
}
|
|
79
79
|
})(HTMLFormElement.prototype);
|
|
80
80
|
|
|
81
|
-
const submittersByForm = new WeakMap;
|
|
81
|
+
const submittersByForm = new WeakMap();
|
|
82
82
|
function findSubmitterFromClickTarget(target) {
|
|
83
83
|
const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
|
|
84
84
|
const candidate = element ? element.closest("input, button") : null;
|
|
@@ -109,15 +109,15 @@ Copyright © 2021 Basecamp, LLC
|
|
|
109
109
|
if (this.type == "submit" && this.target instanceof HTMLFormElement) {
|
|
110
110
|
return submittersByForm.get(this.target);
|
|
111
111
|
}
|
|
112
|
-
}
|
|
112
|
+
},
|
|
113
113
|
});
|
|
114
114
|
})();
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
exports.FrameLoadingStyle = void 0;
|
|
117
117
|
(function (FrameLoadingStyle) {
|
|
118
118
|
FrameLoadingStyle["eager"] = "eager";
|
|
119
119
|
FrameLoadingStyle["lazy"] = "lazy";
|
|
120
|
-
})(FrameLoadingStyle || (FrameLoadingStyle = {}));
|
|
120
|
+
})(exports.FrameLoadingStyle || (exports.FrameLoadingStyle = {}));
|
|
121
121
|
class FrameElement extends HTMLElement {
|
|
122
122
|
constructor() {
|
|
123
123
|
super();
|
|
@@ -125,7 +125,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
125
125
|
this.delegate = new FrameElement.delegateConstructor(this);
|
|
126
126
|
}
|
|
127
127
|
static get observedAttributes() {
|
|
128
|
-
return ["disabled", "loading", "src"];
|
|
128
|
+
return ["disabled", "complete", "loading", "src"];
|
|
129
129
|
}
|
|
130
130
|
connectedCallback() {
|
|
131
131
|
this.delegate.connect();
|
|
@@ -135,13 +135,18 @@ Copyright © 2021 Basecamp, LLC
|
|
|
135
135
|
}
|
|
136
136
|
reload() {
|
|
137
137
|
const { src } = this;
|
|
138
|
+
this.removeAttribute("complete");
|
|
138
139
|
this.src = null;
|
|
139
140
|
this.src = src;
|
|
141
|
+
return this.loaded;
|
|
140
142
|
}
|
|
141
143
|
attributeChangedCallback(name) {
|
|
142
144
|
if (name == "loading") {
|
|
143
145
|
this.delegate.loadingStyleChanged();
|
|
144
146
|
}
|
|
147
|
+
else if (name == "complete") {
|
|
148
|
+
this.delegate.completeChanged();
|
|
149
|
+
}
|
|
145
150
|
else if (name == "src") {
|
|
146
151
|
this.delegate.sourceURLChanged();
|
|
147
152
|
}
|
|
@@ -206,8 +211,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
206
211
|
}
|
|
207
212
|
function frameLoadingStyleFromString(style) {
|
|
208
213
|
switch (style.toLowerCase()) {
|
|
209
|
-
case "lazy":
|
|
210
|
-
|
|
214
|
+
case "lazy":
|
|
215
|
+
return exports.FrameLoadingStyle.lazy;
|
|
216
|
+
default:
|
|
217
|
+
return exports.FrameLoadingStyle.eager;
|
|
211
218
|
}
|
|
212
219
|
}
|
|
213
220
|
|
|
@@ -219,7 +226,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
219
226
|
if (url.hash) {
|
|
220
227
|
return url.hash.slice(1);
|
|
221
228
|
}
|
|
222
|
-
else if (anchorMatch = url.href.match(/#(.*)$/)) {
|
|
229
|
+
else if ((anchorMatch = url.href.match(/#(.*)$/))) {
|
|
223
230
|
return anchorMatch[1];
|
|
224
231
|
}
|
|
225
232
|
}
|
|
@@ -231,7 +238,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
231
238
|
return (getLastPathComponent(url).match(/\.[^.]*$/) || [])[0] || "";
|
|
232
239
|
}
|
|
233
240
|
function isHTML(url) {
|
|
234
|
-
return !!getExtension(url).match(/^(?:|\.(?:htm|html|xhtml))$/);
|
|
241
|
+
return !!getExtension(url).match(/^(?:|\.(?:htm|html|xhtml|php))$/);
|
|
235
242
|
}
|
|
236
243
|
function isPrefixedBy(baseURL, url) {
|
|
237
244
|
const prefix = getPrefix(url);
|
|
@@ -242,9 +249,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
242
249
|
}
|
|
243
250
|
function getRequestURL(url) {
|
|
244
251
|
const anchor = getAnchor(url);
|
|
245
|
-
return anchor != null
|
|
246
|
-
? url.href.slice(0, -(anchor.length + 1))
|
|
247
|
-
: url.href;
|
|
252
|
+
return anchor != null ? url.href.slice(0, -(anchor.length + 1)) : url.href;
|
|
248
253
|
}
|
|
249
254
|
function toCacheKey(url) {
|
|
250
255
|
return getRequestURL(url);
|
|
@@ -312,8 +317,42 @@ Copyright © 2021 Basecamp, LLC
|
|
|
312
317
|
}
|
|
313
318
|
}
|
|
314
319
|
|
|
320
|
+
function isAction(action) {
|
|
321
|
+
return action == "advance" || action == "replace" || action == "restore";
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function activateScriptElement(element) {
|
|
325
|
+
if (element.getAttribute("data-turbo-eval") == "false") {
|
|
326
|
+
return element;
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
const createdScriptElement = document.createElement("script");
|
|
330
|
+
const cspNonce = getMetaContent("csp-nonce");
|
|
331
|
+
if (cspNonce) {
|
|
332
|
+
createdScriptElement.nonce = cspNonce;
|
|
333
|
+
}
|
|
334
|
+
createdScriptElement.textContent = element.textContent;
|
|
335
|
+
createdScriptElement.async = false;
|
|
336
|
+
copyElementAttributes(createdScriptElement, element);
|
|
337
|
+
return createdScriptElement;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
function copyElementAttributes(destinationElement, sourceElement) {
|
|
341
|
+
for (const { name, value } of sourceElement.attributes) {
|
|
342
|
+
destinationElement.setAttribute(name, value);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function createDocumentFragment(html) {
|
|
346
|
+
const template = document.createElement("template");
|
|
347
|
+
template.innerHTML = html;
|
|
348
|
+
return template.content;
|
|
349
|
+
}
|
|
315
350
|
function dispatch(eventName, { target, cancelable, detail } = {}) {
|
|
316
|
-
const event = new CustomEvent(eventName, {
|
|
351
|
+
const event = new CustomEvent(eventName, {
|
|
352
|
+
cancelable,
|
|
353
|
+
bubbles: true,
|
|
354
|
+
detail,
|
|
355
|
+
});
|
|
317
356
|
if (target && target.isConnected) {
|
|
318
357
|
target.dispatchEvent(event);
|
|
319
358
|
}
|
|
@@ -323,10 +362,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
323
362
|
return event;
|
|
324
363
|
}
|
|
325
364
|
function nextAnimationFrame() {
|
|
326
|
-
return new Promise(resolve => requestAnimationFrame(() => resolve()));
|
|
365
|
+
return new Promise((resolve) => requestAnimationFrame(() => resolve()));
|
|
327
366
|
}
|
|
328
367
|
function nextEventLoopTick() {
|
|
329
|
-
return new Promise(resolve => setTimeout(() => resolve(), 0));
|
|
368
|
+
return new Promise((resolve) => setTimeout(() => resolve(), 0));
|
|
330
369
|
}
|
|
331
370
|
function nextMicrotask() {
|
|
332
371
|
return Promise.resolve();
|
|
@@ -338,7 +377,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
338
377
|
const lines = interpolate(strings, values).replace(/^\n/, "").split("\n");
|
|
339
378
|
const match = lines[0].match(/^\s+/);
|
|
340
379
|
const indent = match ? match[0].length : 0;
|
|
341
|
-
return lines.map(line => line.slice(indent)).join("\n");
|
|
380
|
+
return lines.map((line) => line.slice(indent)).join("\n");
|
|
342
381
|
}
|
|
343
382
|
function interpolate(strings, values) {
|
|
344
383
|
return strings.reduce((result, string, i) => {
|
|
@@ -347,7 +386,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
347
386
|
}, "");
|
|
348
387
|
}
|
|
349
388
|
function uuid() {
|
|
350
|
-
return Array.
|
|
389
|
+
return Array.from({ length: 36 })
|
|
390
|
+
.map((_, i) => {
|
|
351
391
|
if (i == 8 || i == 13 || i == 18 || i == 23) {
|
|
352
392
|
return "-";
|
|
353
393
|
}
|
|
@@ -360,15 +400,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
360
400
|
else {
|
|
361
401
|
return Math.floor(Math.random() * 15).toString(16);
|
|
362
402
|
}
|
|
363
|
-
})
|
|
403
|
+
})
|
|
404
|
+
.join("");
|
|
364
405
|
}
|
|
365
406
|
function getAttribute(attributeName, ...elements) {
|
|
366
|
-
for (const value of elements.map(element => element === null || element === void 0 ? void 0 : element.getAttribute(attributeName))) {
|
|
407
|
+
for (const value of elements.map((element) => element === null || element === void 0 ? void 0 : element.getAttribute(attributeName))) {
|
|
367
408
|
if (typeof value == "string")
|
|
368
409
|
return value;
|
|
369
410
|
}
|
|
370
411
|
return null;
|
|
371
412
|
}
|
|
413
|
+
function hasAttribute(attributeName, ...elements) {
|
|
414
|
+
return elements.some((element) => element && element.hasAttribute(attributeName));
|
|
415
|
+
}
|
|
372
416
|
function markAsBusy(...elements) {
|
|
373
417
|
for (const element of elements) {
|
|
374
418
|
if (element.localName == "turbo-frame") {
|
|
@@ -385,6 +429,51 @@ Copyright © 2021 Basecamp, LLC
|
|
|
385
429
|
element.removeAttribute("aria-busy");
|
|
386
430
|
}
|
|
387
431
|
}
|
|
432
|
+
function waitForLoad(element, timeoutInMilliseconds = 2000) {
|
|
433
|
+
return new Promise((resolve) => {
|
|
434
|
+
const onComplete = () => {
|
|
435
|
+
element.removeEventListener("error", onComplete);
|
|
436
|
+
element.removeEventListener("load", onComplete);
|
|
437
|
+
resolve();
|
|
438
|
+
};
|
|
439
|
+
element.addEventListener("load", onComplete, { once: true });
|
|
440
|
+
element.addEventListener("error", onComplete, { once: true });
|
|
441
|
+
setTimeout(resolve, timeoutInMilliseconds);
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
function getHistoryMethodForAction(action) {
|
|
445
|
+
switch (action) {
|
|
446
|
+
case "replace":
|
|
447
|
+
return history.replaceState;
|
|
448
|
+
case "advance":
|
|
449
|
+
case "restore":
|
|
450
|
+
return history.pushState;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
function getVisitAction(...elements) {
|
|
454
|
+
const action = getAttribute("data-turbo-action", ...elements);
|
|
455
|
+
return isAction(action) ? action : null;
|
|
456
|
+
}
|
|
457
|
+
function getBodyElementId() {
|
|
458
|
+
return getMetaContent("turbo-body");
|
|
459
|
+
}
|
|
460
|
+
function getMetaElement(name) {
|
|
461
|
+
return document.querySelector(`meta[name="${name}"]`);
|
|
462
|
+
}
|
|
463
|
+
function getMetaContent(name) {
|
|
464
|
+
const element = getMetaElement(name);
|
|
465
|
+
return element && element.content;
|
|
466
|
+
}
|
|
467
|
+
function setMetaContent(name, content) {
|
|
468
|
+
let element = getMetaElement(name);
|
|
469
|
+
if (!element) {
|
|
470
|
+
element = document.createElement("meta");
|
|
471
|
+
element.setAttribute("name", name);
|
|
472
|
+
document.head.appendChild(element);
|
|
473
|
+
}
|
|
474
|
+
element.setAttribute("content", content);
|
|
475
|
+
return element;
|
|
476
|
+
}
|
|
388
477
|
|
|
389
478
|
var FetchMethod;
|
|
390
479
|
(function (FetchMethod) {
|
|
@@ -396,17 +485,22 @@ Copyright © 2021 Basecamp, LLC
|
|
|
396
485
|
})(FetchMethod || (FetchMethod = {}));
|
|
397
486
|
function fetchMethodFromString(method) {
|
|
398
487
|
switch (method.toLowerCase()) {
|
|
399
|
-
case "get":
|
|
400
|
-
|
|
401
|
-
case "
|
|
402
|
-
|
|
403
|
-
case "
|
|
488
|
+
case "get":
|
|
489
|
+
return FetchMethod.get;
|
|
490
|
+
case "post":
|
|
491
|
+
return FetchMethod.post;
|
|
492
|
+
case "put":
|
|
493
|
+
return FetchMethod.put;
|
|
494
|
+
case "patch":
|
|
495
|
+
return FetchMethod.patch;
|
|
496
|
+
case "delete":
|
|
497
|
+
return FetchMethod.delete;
|
|
404
498
|
}
|
|
405
499
|
}
|
|
406
500
|
class FetchRequest {
|
|
407
|
-
constructor(delegate, method, location, body = new URLSearchParams, target = null) {
|
|
408
|
-
this.abortController = new AbortController;
|
|
409
|
-
this.resolveRequestPromise = (
|
|
501
|
+
constructor(delegate, method, location, body = new URLSearchParams(), target = null) {
|
|
502
|
+
this.abortController = new AbortController();
|
|
503
|
+
this.resolveRequestPromise = (_value) => { };
|
|
410
504
|
this.delegate = delegate;
|
|
411
505
|
this.method = method;
|
|
412
506
|
this.headers = this.defaultHeaders;
|
|
@@ -437,7 +531,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
437
531
|
return await this.receive(response);
|
|
438
532
|
}
|
|
439
533
|
catch (error) {
|
|
440
|
-
if (error.name !==
|
|
534
|
+
if (error.name !== "AbortError") {
|
|
441
535
|
this.delegate.requestErrored(this, error);
|
|
442
536
|
throw error;
|
|
443
537
|
}
|
|
@@ -448,7 +542,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
448
542
|
}
|
|
449
543
|
async receive(response) {
|
|
450
544
|
const fetchResponse = new FetchResponse(response);
|
|
451
|
-
const event = dispatch("turbo:before-fetch-response", {
|
|
545
|
+
const event = dispatch("turbo:before-fetch-response", {
|
|
546
|
+
cancelable: true,
|
|
547
|
+
detail: { fetchResponse },
|
|
548
|
+
target: this.target,
|
|
549
|
+
});
|
|
452
550
|
if (event.defaultPrevented) {
|
|
453
551
|
this.delegate.requestPreventedHandlingResponse(this, fetchResponse);
|
|
454
552
|
}
|
|
@@ -469,12 +567,12 @@ Copyright © 2021 Basecamp, LLC
|
|
|
469
567
|
redirect: "follow",
|
|
470
568
|
body: this.isIdempotent ? null : this.body,
|
|
471
569
|
signal: this.abortSignal,
|
|
472
|
-
referrer: (_a = this.delegate.referrer) === null || _a === void 0 ? void 0 : _a.href
|
|
570
|
+
referrer: (_a = this.delegate.referrer) === null || _a === void 0 ? void 0 : _a.href,
|
|
473
571
|
};
|
|
474
572
|
}
|
|
475
573
|
get defaultHeaders() {
|
|
476
574
|
return {
|
|
477
|
-
|
|
575
|
+
Accept: "text/html, application/xhtml+xml",
|
|
478
576
|
};
|
|
479
577
|
}
|
|
480
578
|
get isIdempotent() {
|
|
@@ -483,16 +581,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
483
581
|
get abortSignal() {
|
|
484
582
|
return this.abortController.signal;
|
|
485
583
|
}
|
|
584
|
+
acceptResponseType(mimeType) {
|
|
585
|
+
this.headers["Accept"] = [mimeType, this.headers["Accept"]].join(", ");
|
|
586
|
+
}
|
|
486
587
|
async allowRequestToBeIntercepted(fetchOptions) {
|
|
487
|
-
const requestInterception = new Promise(resolve => this.resolveRequestPromise = resolve);
|
|
588
|
+
const requestInterception = new Promise((resolve) => (this.resolveRequestPromise = resolve));
|
|
488
589
|
const event = dispatch("turbo:before-fetch-request", {
|
|
489
590
|
cancelable: true,
|
|
490
591
|
detail: {
|
|
491
592
|
fetchOptions,
|
|
492
593
|
url: this.url,
|
|
493
|
-
resume: this.resolveRequestPromise
|
|
594
|
+
resume: this.resolveRequestPromise,
|
|
494
595
|
},
|
|
495
|
-
target: this.target
|
|
596
|
+
target: this.target,
|
|
496
597
|
});
|
|
497
598
|
if (event.defaultPrevented)
|
|
498
599
|
await requestInterception;
|
|
@@ -502,7 +603,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
502
603
|
class AppearanceObserver {
|
|
503
604
|
constructor(delegate, element) {
|
|
504
605
|
this.started = false;
|
|
505
|
-
this.intersect = entries => {
|
|
606
|
+
this.intersect = (entries) => {
|
|
506
607
|
const lastEntry = entries.slice(-1)[0];
|
|
507
608
|
if (lastEntry === null || lastEntry === void 0 ? void 0 : lastEntry.isIntersecting) {
|
|
508
609
|
this.delegate.elementAppearedInViewport(this.element);
|
|
@@ -527,40 +628,29 @@ Copyright © 2021 Basecamp, LLC
|
|
|
527
628
|
}
|
|
528
629
|
|
|
529
630
|
class StreamMessage {
|
|
530
|
-
constructor(
|
|
531
|
-
this.
|
|
532
|
-
this.templateElement.innerHTML = html;
|
|
631
|
+
constructor(fragment) {
|
|
632
|
+
this.fragment = importStreamElements(fragment);
|
|
533
633
|
}
|
|
534
634
|
static wrap(message) {
|
|
535
635
|
if (typeof message == "string") {
|
|
536
|
-
return new this(message);
|
|
636
|
+
return new this(createDocumentFragment(message));
|
|
537
637
|
}
|
|
538
638
|
else {
|
|
539
639
|
return message;
|
|
540
640
|
}
|
|
541
641
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
642
|
+
}
|
|
643
|
+
StreamMessage.contentType = "text/vnd.turbo-stream.html";
|
|
644
|
+
function importStreamElements(fragment) {
|
|
645
|
+
for (const element of fragment.querySelectorAll("turbo-stream")) {
|
|
646
|
+
const streamElement = document.importNode(element, true);
|
|
647
|
+
for (const inertScriptElement of streamElement.templateElement.content.querySelectorAll("script")) {
|
|
648
|
+
inertScriptElement.replaceWith(activateScriptElement(inertScriptElement));
|
|
546
649
|
}
|
|
547
|
-
|
|
548
|
-
}
|
|
549
|
-
get foreignElements() {
|
|
550
|
-
return this.templateChildren.reduce((streamElements, child) => {
|
|
551
|
-
if (child.tagName.toLowerCase() == "turbo-stream") {
|
|
552
|
-
return [...streamElements, child];
|
|
553
|
-
}
|
|
554
|
-
else {
|
|
555
|
-
return streamElements;
|
|
556
|
-
}
|
|
557
|
-
}, []);
|
|
558
|
-
}
|
|
559
|
-
get templateChildren() {
|
|
560
|
-
return Array.from(this.templateElement.content.children);
|
|
650
|
+
element.replaceWith(streamElement);
|
|
561
651
|
}
|
|
652
|
+
return fragment;
|
|
562
653
|
}
|
|
563
|
-
StreamMessage.contentType = "text/vnd.turbo-stream.html";
|
|
564
654
|
|
|
565
655
|
var FormSubmissionState;
|
|
566
656
|
(function (FormSubmissionState) {
|
|
@@ -579,9 +669,12 @@ Copyright © 2021 Basecamp, LLC
|
|
|
579
669
|
})(FormEnctype || (FormEnctype = {}));
|
|
580
670
|
function formEnctypeFromString(encoding) {
|
|
581
671
|
switch (encoding.toLowerCase()) {
|
|
582
|
-
case FormEnctype.multipart:
|
|
583
|
-
|
|
584
|
-
|
|
672
|
+
case FormEnctype.multipart:
|
|
673
|
+
return FormEnctype.multipart;
|
|
674
|
+
case FormEnctype.plain:
|
|
675
|
+
return FormEnctype.plain;
|
|
676
|
+
default:
|
|
677
|
+
return FormEnctype.urlEncoded;
|
|
585
678
|
}
|
|
586
679
|
}
|
|
587
680
|
class FormSubmission {
|
|
@@ -598,8 +691,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
598
691
|
this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
|
|
599
692
|
this.mustRedirect = mustRedirect;
|
|
600
693
|
}
|
|
601
|
-
static confirmMethod(message,
|
|
602
|
-
return confirm(message);
|
|
694
|
+
static confirmMethod(message, _element, _submitter) {
|
|
695
|
+
return Promise.resolve(confirm(message));
|
|
603
696
|
}
|
|
604
697
|
get method() {
|
|
605
698
|
var _a;
|
|
@@ -608,8 +701,13 @@ Copyright © 2021 Basecamp, LLC
|
|
|
608
701
|
}
|
|
609
702
|
get action() {
|
|
610
703
|
var _a;
|
|
611
|
-
const formElementAction = typeof this.formElement.action ===
|
|
612
|
-
|
|
704
|
+
const formElementAction = typeof this.formElement.action === "string" ? this.formElement.action : null;
|
|
705
|
+
if ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.hasAttribute("formaction")) {
|
|
706
|
+
return this.submitter.getAttribute("formaction") || "";
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
return this.formElement.getAttribute("action") || formElementAction || "";
|
|
710
|
+
}
|
|
613
711
|
}
|
|
614
712
|
get body() {
|
|
615
713
|
if (this.enctype == FormEnctype.urlEncoded || this.method == FetchMethod.get) {
|
|
@@ -631,16 +729,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
631
729
|
return entries.concat(typeof value == "string" ? [[name, value]] : []);
|
|
632
730
|
}, []);
|
|
633
731
|
}
|
|
634
|
-
get confirmationMessage() {
|
|
635
|
-
return this.formElement.getAttribute("data-turbo-confirm");
|
|
636
|
-
}
|
|
637
|
-
get needsConfirmation() {
|
|
638
|
-
return this.confirmationMessage !== null;
|
|
639
|
-
}
|
|
640
732
|
async start() {
|
|
641
733
|
const { initialized, requesting } = FormSubmissionState;
|
|
642
|
-
|
|
643
|
-
|
|
734
|
+
const confirmationMessage = getAttribute("data-turbo-confirm", this.submitter, this.formElement);
|
|
735
|
+
if (typeof confirmationMessage === "string") {
|
|
736
|
+
const answer = await FormSubmission.confirmMethod(confirmationMessage, this.formElement, this.submitter);
|
|
644
737
|
if (!answer) {
|
|
645
738
|
return;
|
|
646
739
|
}
|
|
@@ -664,14 +757,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
664
757
|
if (token) {
|
|
665
758
|
headers["X-CSRF-Token"] = token;
|
|
666
759
|
}
|
|
667
|
-
|
|
760
|
+
}
|
|
761
|
+
if (this.requestAcceptsTurboStreamResponse(request)) {
|
|
762
|
+
request.acceptResponseType(StreamMessage.contentType);
|
|
668
763
|
}
|
|
669
764
|
}
|
|
670
|
-
requestStarted(
|
|
765
|
+
requestStarted(_request) {
|
|
671
766
|
var _a;
|
|
672
767
|
this.state = FormSubmissionState.waiting;
|
|
673
768
|
(_a = this.submitter) === null || _a === void 0 ? void 0 : _a.setAttribute("disabled", "");
|
|
674
|
-
dispatch("turbo:submit-start", {
|
|
769
|
+
dispatch("turbo:submit-start", {
|
|
770
|
+
target: this.formElement,
|
|
771
|
+
detail: { formSubmission: this },
|
|
772
|
+
});
|
|
675
773
|
this.delegate.formSubmissionStarted(this);
|
|
676
774
|
}
|
|
677
775
|
requestPreventedHandlingResponse(request, response) {
|
|
@@ -697,25 +795,35 @@ Copyright © 2021 Basecamp, LLC
|
|
|
697
795
|
}
|
|
698
796
|
requestErrored(request, error) {
|
|
699
797
|
this.result = { success: false, error };
|
|
798
|
+
dispatch("turbo:fetch-request-error", {
|
|
799
|
+
target: this.formElement,
|
|
800
|
+
detail: { request, error },
|
|
801
|
+
});
|
|
700
802
|
this.delegate.formSubmissionErrored(this, error);
|
|
701
803
|
}
|
|
702
|
-
requestFinished(
|
|
804
|
+
requestFinished(_request) {
|
|
703
805
|
var _a;
|
|
704
806
|
this.state = FormSubmissionState.stopped;
|
|
705
807
|
(_a = this.submitter) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled");
|
|
706
|
-
dispatch("turbo:submit-end", {
|
|
808
|
+
dispatch("turbo:submit-end", {
|
|
809
|
+
target: this.formElement,
|
|
810
|
+
detail: Object.assign({ formSubmission: this }, this.result),
|
|
811
|
+
});
|
|
707
812
|
this.delegate.formSubmissionFinished(this);
|
|
708
813
|
}
|
|
709
814
|
requestMustRedirect(request) {
|
|
710
815
|
return !request.isIdempotent && this.mustRedirect;
|
|
711
816
|
}
|
|
817
|
+
requestAcceptsTurboStreamResponse(request) {
|
|
818
|
+
return !request.isIdempotent || hasAttribute("data-turbo-stream", this.submitter, this.formElement);
|
|
819
|
+
}
|
|
712
820
|
}
|
|
713
821
|
function buildFormData(formElement, submitter) {
|
|
714
822
|
const formData = new FormData(formElement);
|
|
715
823
|
const name = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("name");
|
|
716
824
|
const value = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("value");
|
|
717
|
-
if (name
|
|
718
|
-
formData.append(name, value);
|
|
825
|
+
if (name) {
|
|
826
|
+
formData.append(name, value || "");
|
|
719
827
|
}
|
|
720
828
|
return formData;
|
|
721
829
|
}
|
|
@@ -729,15 +837,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
729
837
|
}
|
|
730
838
|
}
|
|
731
839
|
}
|
|
732
|
-
function getMetaContent(name) {
|
|
733
|
-
const element = document.querySelector(`meta[name="${name}"]`);
|
|
734
|
-
return element && element.content;
|
|
735
|
-
}
|
|
736
840
|
function responseSucceededWithoutRedirect(response) {
|
|
737
841
|
return response.statusCode == 200 && !response.redirected;
|
|
738
842
|
}
|
|
739
843
|
function mergeFormDataEntries(url, entries) {
|
|
740
|
-
const searchParams = new URLSearchParams;
|
|
844
|
+
const searchParams = new URLSearchParams();
|
|
741
845
|
for (const [name, value] of entries) {
|
|
742
846
|
if (value instanceof File)
|
|
743
847
|
continue;
|
|
@@ -751,6 +855,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
751
855
|
constructor(element) {
|
|
752
856
|
this.element = element;
|
|
753
857
|
}
|
|
858
|
+
get activeElement() {
|
|
859
|
+
return this.element.ownerDocument.activeElement;
|
|
860
|
+
}
|
|
754
861
|
get children() {
|
|
755
862
|
return [...this.element.children];
|
|
756
863
|
}
|
|
@@ -764,13 +871,20 @@ Copyright © 2021 Basecamp, LLC
|
|
|
764
871
|
return this.element.isConnected;
|
|
765
872
|
}
|
|
766
873
|
get firstAutofocusableElement() {
|
|
767
|
-
|
|
874
|
+
const inertDisabledOrHidden = "[inert], :disabled, [hidden], details:not([open]), dialog:not([open])";
|
|
875
|
+
for (const element of this.element.querySelectorAll("[autofocus]")) {
|
|
876
|
+
if (element.closest(inertDisabledOrHidden) == null)
|
|
877
|
+
return element;
|
|
878
|
+
else
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
881
|
+
return null;
|
|
768
882
|
}
|
|
769
883
|
get permanentElements() {
|
|
770
|
-
return
|
|
884
|
+
return queryPermanentElementsAll(this.element);
|
|
771
885
|
}
|
|
772
886
|
getPermanentElementById(id) {
|
|
773
|
-
return this.element
|
|
887
|
+
return getPermanentElementById(this.element, id);
|
|
774
888
|
}
|
|
775
889
|
getPermanentElementMapForSnapshot(snapshot) {
|
|
776
890
|
const permanentElementMap = {};
|
|
@@ -784,36 +898,66 @@ Copyright © 2021 Basecamp, LLC
|
|
|
784
898
|
return permanentElementMap;
|
|
785
899
|
}
|
|
786
900
|
}
|
|
901
|
+
function getPermanentElementById(node, id) {
|
|
902
|
+
return node.querySelector(`#${id}[data-turbo-permanent]`);
|
|
903
|
+
}
|
|
904
|
+
function queryPermanentElementsAll(node) {
|
|
905
|
+
return node.querySelectorAll("[id][data-turbo-permanent]");
|
|
906
|
+
}
|
|
787
907
|
|
|
788
|
-
class
|
|
789
|
-
constructor(delegate,
|
|
908
|
+
class FormSubmitObserver {
|
|
909
|
+
constructor(delegate, eventTarget) {
|
|
910
|
+
this.started = false;
|
|
911
|
+
this.submitCaptured = () => {
|
|
912
|
+
this.eventTarget.removeEventListener("submit", this.submitBubbled, false);
|
|
913
|
+
this.eventTarget.addEventListener("submit", this.submitBubbled, false);
|
|
914
|
+
};
|
|
790
915
|
this.submitBubbled = ((event) => {
|
|
791
|
-
|
|
792
|
-
|
|
916
|
+
if (!event.defaultPrevented) {
|
|
917
|
+
const form = event.target instanceof HTMLFormElement ? event.target : undefined;
|
|
793
918
|
const submitter = event.submitter || undefined;
|
|
794
|
-
|
|
795
|
-
|
|
919
|
+
if (form &&
|
|
920
|
+
submissionDoesNotDismissDialog(form, submitter) &&
|
|
921
|
+
submissionDoesNotTargetIFrame(form, submitter) &&
|
|
922
|
+
this.delegate.willSubmitForm(form, submitter)) {
|
|
796
923
|
event.preventDefault();
|
|
797
|
-
|
|
798
|
-
this.delegate.formSubmissionIntercepted(form, submitter);
|
|
924
|
+
this.delegate.formSubmitted(form, submitter);
|
|
799
925
|
}
|
|
800
926
|
}
|
|
801
927
|
});
|
|
802
928
|
this.delegate = delegate;
|
|
803
|
-
this.
|
|
929
|
+
this.eventTarget = eventTarget;
|
|
804
930
|
}
|
|
805
931
|
start() {
|
|
806
|
-
|
|
932
|
+
if (!this.started) {
|
|
933
|
+
this.eventTarget.addEventListener("submit", this.submitCaptured, true);
|
|
934
|
+
this.started = true;
|
|
935
|
+
}
|
|
807
936
|
}
|
|
808
937
|
stop() {
|
|
809
|
-
|
|
938
|
+
if (this.started) {
|
|
939
|
+
this.eventTarget.removeEventListener("submit", this.submitCaptured, true);
|
|
940
|
+
this.started = false;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
function submissionDoesNotDismissDialog(form, submitter) {
|
|
945
|
+
const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.getAttribute("method");
|
|
946
|
+
return method != "dialog";
|
|
947
|
+
}
|
|
948
|
+
function submissionDoesNotTargetIFrame(form, submitter) {
|
|
949
|
+
const target = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formtarget")) || form.target;
|
|
950
|
+
for (const element of document.getElementsByName(target)) {
|
|
951
|
+
if (element instanceof HTMLIFrameElement)
|
|
952
|
+
return false;
|
|
810
953
|
}
|
|
954
|
+
return true;
|
|
811
955
|
}
|
|
812
956
|
|
|
813
957
|
class View {
|
|
814
958
|
constructor(delegate, element) {
|
|
815
|
-
this.resolveRenderPromise = (
|
|
816
|
-
this.resolveInterceptionPromise = (
|
|
959
|
+
this.resolveRenderPromise = (_value) => { };
|
|
960
|
+
this.resolveInterceptionPromise = (_value) => { };
|
|
817
961
|
this.delegate = delegate;
|
|
818
962
|
this.element = element;
|
|
819
963
|
}
|
|
@@ -858,15 +1002,17 @@ Copyright © 2021 Basecamp, LLC
|
|
|
858
1002
|
const { isPreview, shouldRender, newSnapshot: snapshot } = renderer;
|
|
859
1003
|
if (shouldRender) {
|
|
860
1004
|
try {
|
|
861
|
-
this.renderPromise = new Promise(resolve => this.resolveRenderPromise = resolve);
|
|
1005
|
+
this.renderPromise = new Promise((resolve) => (this.resolveRenderPromise = resolve));
|
|
862
1006
|
this.renderer = renderer;
|
|
863
|
-
this.prepareToRenderSnapshot(renderer);
|
|
864
|
-
const renderInterception = new Promise(resolve => this.resolveInterceptionPromise = resolve);
|
|
865
|
-
const
|
|
1007
|
+
await this.prepareToRenderSnapshot(renderer);
|
|
1008
|
+
const renderInterception = new Promise((resolve) => (this.resolveInterceptionPromise = resolve));
|
|
1009
|
+
const options = { resume: this.resolveInterceptionPromise, render: this.renderer.renderElement };
|
|
1010
|
+
const immediateRender = this.delegate.allowsImmediateRender(snapshot, options);
|
|
866
1011
|
if (!immediateRender)
|
|
867
1012
|
await renderInterception;
|
|
868
1013
|
await this.renderSnapshot(renderer);
|
|
869
1014
|
this.delegate.viewRenderedSnapshot(snapshot, isPreview);
|
|
1015
|
+
this.delegate.preloadOnLoadLinksForView(this.element);
|
|
870
1016
|
this.finishRenderingSnapshot(renderer);
|
|
871
1017
|
}
|
|
872
1018
|
finally {
|
|
@@ -876,15 +1022,15 @@ Copyright © 2021 Basecamp, LLC
|
|
|
876
1022
|
}
|
|
877
1023
|
}
|
|
878
1024
|
else {
|
|
879
|
-
this.invalidate();
|
|
1025
|
+
this.invalidate(renderer.reloadReason);
|
|
880
1026
|
}
|
|
881
1027
|
}
|
|
882
|
-
invalidate() {
|
|
883
|
-
this.delegate.viewInvalidated();
|
|
1028
|
+
invalidate(reason) {
|
|
1029
|
+
this.delegate.viewInvalidated(reason);
|
|
884
1030
|
}
|
|
885
|
-
prepareToRenderSnapshot(renderer) {
|
|
1031
|
+
async prepareToRenderSnapshot(renderer) {
|
|
886
1032
|
this.markAsPreview(renderer.isPreview);
|
|
887
|
-
renderer.prepareToRender();
|
|
1033
|
+
await renderer.prepareToRender();
|
|
888
1034
|
}
|
|
889
1035
|
markAsPreview(isPreview) {
|
|
890
1036
|
if (isPreview) {
|
|
@@ -911,65 +1057,125 @@ Copyright © 2021 Basecamp, LLC
|
|
|
911
1057
|
}
|
|
912
1058
|
}
|
|
913
1059
|
|
|
914
|
-
class
|
|
915
|
-
constructor(delegate,
|
|
916
|
-
this.
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
else {
|
|
921
|
-
delete this.clickEvent;
|
|
922
|
-
}
|
|
1060
|
+
class LinkClickObserver {
|
|
1061
|
+
constructor(delegate, eventTarget) {
|
|
1062
|
+
this.started = false;
|
|
1063
|
+
this.clickCaptured = () => {
|
|
1064
|
+
this.eventTarget.removeEventListener("click", this.clickBubbled, false);
|
|
1065
|
+
this.eventTarget.addEventListener("click", this.clickBubbled, false);
|
|
923
1066
|
};
|
|
924
|
-
this.
|
|
925
|
-
if (
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
this.
|
|
1067
|
+
this.clickBubbled = (event) => {
|
|
1068
|
+
if (event instanceof MouseEvent && this.clickEventIsSignificant(event)) {
|
|
1069
|
+
const target = (event.composedPath && event.composedPath()[0]) || event.target;
|
|
1070
|
+
const link = this.findLinkFromClickTarget(target);
|
|
1071
|
+
if (link && doesNotTargetIFrame(link)) {
|
|
1072
|
+
const location = this.getLocationForLink(link);
|
|
1073
|
+
if (this.delegate.willFollowLinkToLocation(link, location, event)) {
|
|
1074
|
+
event.preventDefault();
|
|
1075
|
+
this.delegate.followedLinkToLocation(link, location);
|
|
1076
|
+
}
|
|
930
1077
|
}
|
|
931
1078
|
}
|
|
932
|
-
delete this.clickEvent;
|
|
933
|
-
});
|
|
934
|
-
this.willVisit = () => {
|
|
935
|
-
delete this.clickEvent;
|
|
936
1079
|
};
|
|
937
1080
|
this.delegate = delegate;
|
|
938
|
-
this.
|
|
1081
|
+
this.eventTarget = eventTarget;
|
|
1082
|
+
}
|
|
1083
|
+
start() {
|
|
1084
|
+
if (!this.started) {
|
|
1085
|
+
this.eventTarget.addEventListener("click", this.clickCaptured, true);
|
|
1086
|
+
this.started = true;
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
stop() {
|
|
1090
|
+
if (this.started) {
|
|
1091
|
+
this.eventTarget.removeEventListener("click", this.clickCaptured, true);
|
|
1092
|
+
this.started = false;
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
clickEventIsSignificant(event) {
|
|
1096
|
+
return !((event.target && event.target.isContentEditable) ||
|
|
1097
|
+
event.defaultPrevented ||
|
|
1098
|
+
event.which > 1 ||
|
|
1099
|
+
event.altKey ||
|
|
1100
|
+
event.ctrlKey ||
|
|
1101
|
+
event.metaKey ||
|
|
1102
|
+
event.shiftKey);
|
|
1103
|
+
}
|
|
1104
|
+
findLinkFromClickTarget(target) {
|
|
1105
|
+
if (target instanceof Element) {
|
|
1106
|
+
return target.closest("a[href]:not([target^=_]):not([download])");
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
getLocationForLink(link) {
|
|
1110
|
+
return expandURL(link.getAttribute("href") || "");
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
function doesNotTargetIFrame(anchor) {
|
|
1114
|
+
for (const element of document.getElementsByName(anchor.target)) {
|
|
1115
|
+
if (element instanceof HTMLIFrameElement)
|
|
1116
|
+
return false;
|
|
1117
|
+
}
|
|
1118
|
+
return true;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
class FormLinkClickObserver {
|
|
1122
|
+
constructor(delegate, element) {
|
|
1123
|
+
this.delegate = delegate;
|
|
1124
|
+
this.linkClickObserver = new LinkClickObserver(this, element);
|
|
939
1125
|
}
|
|
940
1126
|
start() {
|
|
941
|
-
this.
|
|
942
|
-
document.addEventListener("turbo:click", this.linkClicked);
|
|
943
|
-
document.addEventListener("turbo:before-visit", this.willVisit);
|
|
1127
|
+
this.linkClickObserver.start();
|
|
944
1128
|
}
|
|
945
1129
|
stop() {
|
|
946
|
-
this.
|
|
947
|
-
|
|
948
|
-
|
|
1130
|
+
this.linkClickObserver.stop();
|
|
1131
|
+
}
|
|
1132
|
+
willFollowLinkToLocation(link, location, originalEvent) {
|
|
1133
|
+
return (this.delegate.willSubmitFormLinkToLocation(link, location, originalEvent) &&
|
|
1134
|
+
link.hasAttribute("data-turbo-method"));
|
|
949
1135
|
}
|
|
950
|
-
|
|
951
|
-
const
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
1136
|
+
followedLinkToLocation(link, location) {
|
|
1137
|
+
const action = location.href;
|
|
1138
|
+
const form = document.createElement("form");
|
|
1139
|
+
form.setAttribute("data-turbo", "true");
|
|
1140
|
+
form.setAttribute("action", action);
|
|
1141
|
+
form.setAttribute("hidden", "");
|
|
1142
|
+
const method = link.getAttribute("data-turbo-method");
|
|
1143
|
+
if (method)
|
|
1144
|
+
form.setAttribute("method", method);
|
|
1145
|
+
const turboFrame = link.getAttribute("data-turbo-frame");
|
|
1146
|
+
if (turboFrame)
|
|
1147
|
+
form.setAttribute("data-turbo-frame", turboFrame);
|
|
1148
|
+
const turboAction = link.getAttribute("data-turbo-action");
|
|
1149
|
+
if (turboAction)
|
|
1150
|
+
form.setAttribute("data-turbo-action", turboAction);
|
|
1151
|
+
const turboConfirm = link.getAttribute("data-turbo-confirm");
|
|
1152
|
+
if (turboConfirm)
|
|
1153
|
+
form.setAttribute("data-turbo-confirm", turboConfirm);
|
|
1154
|
+
const turboStream = link.hasAttribute("data-turbo-stream");
|
|
1155
|
+
if (turboStream)
|
|
1156
|
+
form.setAttribute("data-turbo-stream", "");
|
|
1157
|
+
this.delegate.submittedFormLinkToLocation(link, location, form);
|
|
1158
|
+
document.body.appendChild(form);
|
|
1159
|
+
form.addEventListener("turbo:submit-end", () => form.remove(), { once: true });
|
|
1160
|
+
requestAnimationFrame(() => form.requestSubmit());
|
|
957
1161
|
}
|
|
958
1162
|
}
|
|
959
1163
|
|
|
960
1164
|
class Bardo {
|
|
961
|
-
constructor(permanentElementMap) {
|
|
1165
|
+
constructor(delegate, permanentElementMap) {
|
|
1166
|
+
this.delegate = delegate;
|
|
962
1167
|
this.permanentElementMap = permanentElementMap;
|
|
963
1168
|
}
|
|
964
|
-
static preservingPermanentElements(permanentElementMap, callback) {
|
|
965
|
-
const bardo = new this(permanentElementMap);
|
|
1169
|
+
static preservingPermanentElements(delegate, permanentElementMap, callback) {
|
|
1170
|
+
const bardo = new this(delegate, permanentElementMap);
|
|
966
1171
|
bardo.enter();
|
|
967
1172
|
callback();
|
|
968
1173
|
bardo.leave();
|
|
969
1174
|
}
|
|
970
1175
|
enter() {
|
|
971
1176
|
for (const id in this.permanentElementMap) {
|
|
972
|
-
const [, newPermanentElement] = this.permanentElementMap[id];
|
|
1177
|
+
const [currentPermanentElement, newPermanentElement] = this.permanentElementMap[id];
|
|
1178
|
+
this.delegate.enteringBardo(currentPermanentElement, newPermanentElement);
|
|
973
1179
|
this.replaceNewPermanentElementWithPlaceholder(newPermanentElement);
|
|
974
1180
|
}
|
|
975
1181
|
}
|
|
@@ -978,6 +1184,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
978
1184
|
const [currentPermanentElement] = this.permanentElementMap[id];
|
|
979
1185
|
this.replaceCurrentPermanentElementWithClone(currentPermanentElement);
|
|
980
1186
|
this.replacePlaceholderWithPermanentElement(currentPermanentElement);
|
|
1187
|
+
this.delegate.leavingBardo(currentPermanentElement);
|
|
981
1188
|
}
|
|
982
1189
|
}
|
|
983
1190
|
replaceNewPermanentElementWithPlaceholder(permanentElement) {
|
|
@@ -993,7 +1200,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
993
1200
|
placeholder === null || placeholder === void 0 ? void 0 : placeholder.replaceWith(permanentElement);
|
|
994
1201
|
}
|
|
995
1202
|
getPlaceholderById(id) {
|
|
996
|
-
return this.placeholders.find(element => element.content == id);
|
|
1203
|
+
return this.placeholders.find((element) => element.content == id);
|
|
997
1204
|
}
|
|
998
1205
|
get placeholders() {
|
|
999
1206
|
return [...document.querySelectorAll("meta[name=turbo-permanent-placeholder][content]")];
|
|
@@ -1007,16 +1214,21 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1007
1214
|
}
|
|
1008
1215
|
|
|
1009
1216
|
class Renderer {
|
|
1010
|
-
constructor(currentSnapshot, newSnapshot, isPreview, willRender = true) {
|
|
1217
|
+
constructor(currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
|
|
1218
|
+
this.activeElement = null;
|
|
1011
1219
|
this.currentSnapshot = currentSnapshot;
|
|
1012
1220
|
this.newSnapshot = newSnapshot;
|
|
1013
1221
|
this.isPreview = isPreview;
|
|
1014
1222
|
this.willRender = willRender;
|
|
1015
|
-
this.
|
|
1223
|
+
this.renderElement = renderElement;
|
|
1224
|
+
this.promise = new Promise((resolve, reject) => (this.resolvingFunctions = { resolve, reject }));
|
|
1016
1225
|
}
|
|
1017
1226
|
get shouldRender() {
|
|
1018
1227
|
return true;
|
|
1019
1228
|
}
|
|
1229
|
+
get reloadReason() {
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1020
1232
|
prepareToRender() {
|
|
1021
1233
|
return;
|
|
1022
1234
|
}
|
|
@@ -1026,23 +1238,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1026
1238
|
delete this.resolvingFunctions;
|
|
1027
1239
|
}
|
|
1028
1240
|
}
|
|
1029
|
-
createScriptElement(element) {
|
|
1030
|
-
if (element.getAttribute("data-turbo-eval") == "false") {
|
|
1031
|
-
return element;
|
|
1032
|
-
}
|
|
1033
|
-
else {
|
|
1034
|
-
const createdScriptElement = document.createElement("script");
|
|
1035
|
-
if (this.cspNonce) {
|
|
1036
|
-
createdScriptElement.nonce = this.cspNonce;
|
|
1037
|
-
}
|
|
1038
|
-
createdScriptElement.textContent = element.textContent;
|
|
1039
|
-
createdScriptElement.async = false;
|
|
1040
|
-
copyElementAttributes(createdScriptElement, element);
|
|
1041
|
-
return createdScriptElement;
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
1241
|
preservingPermanentElements(callback) {
|
|
1045
|
-
Bardo.preservingPermanentElements(this.permanentElementMap, callback);
|
|
1242
|
+
Bardo.preservingPermanentElements(this, this.permanentElementMap, callback);
|
|
1046
1243
|
}
|
|
1047
1244
|
focusFirstAutofocusableElement() {
|
|
1048
1245
|
const element = this.connectedSnapshot.firstAutofocusableElement;
|
|
@@ -1050,6 +1247,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1050
1247
|
element.focus();
|
|
1051
1248
|
}
|
|
1052
1249
|
}
|
|
1250
|
+
enteringBardo(currentPermanentElement) {
|
|
1251
|
+
if (this.activeElement)
|
|
1252
|
+
return;
|
|
1253
|
+
if (currentPermanentElement.contains(this.currentSnapshot.activeElement)) {
|
|
1254
|
+
this.activeElement = this.currentSnapshot.activeElement;
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
leavingBardo(currentPermanentElement) {
|
|
1258
|
+
if (currentPermanentElement.contains(this.activeElement) && this.activeElement instanceof HTMLElement) {
|
|
1259
|
+
this.activeElement.focus();
|
|
1260
|
+
this.activeElement = null;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1053
1263
|
get connectedSnapshot() {
|
|
1054
1264
|
return this.newSnapshot.isConnected ? this.newSnapshot : this.currentSnapshot;
|
|
1055
1265
|
}
|
|
@@ -1062,21 +1272,28 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1062
1272
|
get permanentElementMap() {
|
|
1063
1273
|
return this.currentSnapshot.getPermanentElementMapForSnapshot(this.newSnapshot);
|
|
1064
1274
|
}
|
|
1065
|
-
get cspNonce() {
|
|
1066
|
-
var _a;
|
|
1067
|
-
return (_a = document.head.querySelector('meta[name="csp-nonce"]')) === null || _a === void 0 ? void 0 : _a.getAttribute("content");
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
function copyElementAttributes(destinationElement, sourceElement) {
|
|
1071
|
-
for (const { name, value } of [...sourceElement.attributes]) {
|
|
1072
|
-
destinationElement.setAttribute(name, value);
|
|
1073
|
-
}
|
|
1074
1275
|
}
|
|
1075
1276
|
function elementIsFocusable(element) {
|
|
1076
1277
|
return element && typeof element.focus == "function";
|
|
1077
1278
|
}
|
|
1078
1279
|
|
|
1079
1280
|
class FrameRenderer extends Renderer {
|
|
1281
|
+
constructor(delegate, currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
|
|
1282
|
+
super(currentSnapshot, newSnapshot, renderElement, isPreview, willRender);
|
|
1283
|
+
this.delegate = delegate;
|
|
1284
|
+
}
|
|
1285
|
+
static renderElement(currentElement, newElement) {
|
|
1286
|
+
var _a;
|
|
1287
|
+
const destinationRange = document.createRange();
|
|
1288
|
+
destinationRange.selectNodeContents(currentElement);
|
|
1289
|
+
destinationRange.deleteContents();
|
|
1290
|
+
const frameElement = newElement;
|
|
1291
|
+
const sourceRange = (_a = frameElement.ownerDocument) === null || _a === void 0 ? void 0 : _a.createRange();
|
|
1292
|
+
if (sourceRange) {
|
|
1293
|
+
sourceRange.selectNodeContents(frameElement);
|
|
1294
|
+
currentElement.appendChild(sourceRange.extractContents());
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1080
1297
|
get shouldRender() {
|
|
1081
1298
|
return true;
|
|
1082
1299
|
}
|
|
@@ -1092,23 +1309,16 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1092
1309
|
this.activateScriptElements();
|
|
1093
1310
|
}
|
|
1094
1311
|
loadFrameElement() {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
destinationRange.selectNodeContents(this.currentElement);
|
|
1098
|
-
destinationRange.deleteContents();
|
|
1099
|
-
const frameElement = this.newElement;
|
|
1100
|
-
const sourceRange = (_a = frameElement.ownerDocument) === null || _a === void 0 ? void 0 : _a.createRange();
|
|
1101
|
-
if (sourceRange) {
|
|
1102
|
-
sourceRange.selectNodeContents(frameElement);
|
|
1103
|
-
this.currentElement.appendChild(sourceRange.extractContents());
|
|
1104
|
-
}
|
|
1312
|
+
this.delegate.willRenderFrame(this.currentElement, this.newElement);
|
|
1313
|
+
this.renderElement(this.currentElement, this.newElement);
|
|
1105
1314
|
}
|
|
1106
1315
|
scrollFrameIntoView() {
|
|
1107
1316
|
if (this.currentElement.autoscroll || this.newElement.autoscroll) {
|
|
1108
1317
|
const element = this.currentElement.firstElementChild;
|
|
1109
1318
|
const block = readScrollLogicalPosition(this.currentElement.getAttribute("data-autoscroll-block"), "end");
|
|
1319
|
+
const behavior = readScrollBehavior(this.currentElement.getAttribute("data-autoscroll-behavior"), "auto");
|
|
1110
1320
|
if (element) {
|
|
1111
|
-
element.scrollIntoView({ block });
|
|
1321
|
+
element.scrollIntoView({ block, behavior });
|
|
1112
1322
|
return true;
|
|
1113
1323
|
}
|
|
1114
1324
|
}
|
|
@@ -1116,7 +1326,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1116
1326
|
}
|
|
1117
1327
|
activateScriptElements() {
|
|
1118
1328
|
for (const inertScriptElement of this.newScriptElements) {
|
|
1119
|
-
const activatedScriptElement =
|
|
1329
|
+
const activatedScriptElement = activateScriptElement(inertScriptElement);
|
|
1120
1330
|
inertScriptElement.replaceWith(activatedScriptElement);
|
|
1121
1331
|
}
|
|
1122
1332
|
}
|
|
@@ -1132,6 +1342,14 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1132
1342
|
return defaultValue;
|
|
1133
1343
|
}
|
|
1134
1344
|
}
|
|
1345
|
+
function readScrollBehavior(value, defaultValue) {
|
|
1346
|
+
if (value == "auto" || value == "smooth") {
|
|
1347
|
+
return value;
|
|
1348
|
+
}
|
|
1349
|
+
else {
|
|
1350
|
+
return defaultValue;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1135
1353
|
|
|
1136
1354
|
class ProgressBar {
|
|
1137
1355
|
constructor() {
|
|
@@ -1155,7 +1373,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1155
1373
|
left: 0;
|
|
1156
1374
|
height: 3px;
|
|
1157
1375
|
background: #0076ff;
|
|
1158
|
-
z-index:
|
|
1376
|
+
z-index: 2147483647;
|
|
1159
1377
|
transition:
|
|
1160
1378
|
width ${ProgressBar.animationDuration}ms ease-out,
|
|
1161
1379
|
opacity ${ProgressBar.animationDuration / 2}ms ${ProgressBar.animationDuration / 2}ms ease-in;
|
|
@@ -1214,13 +1432,16 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1214
1432
|
}
|
|
1215
1433
|
refresh() {
|
|
1216
1434
|
requestAnimationFrame(() => {
|
|
1217
|
-
this.progressElement.style.width = `${10 +
|
|
1435
|
+
this.progressElement.style.width = `${10 + this.value * 90}%`;
|
|
1218
1436
|
});
|
|
1219
1437
|
}
|
|
1220
1438
|
createStylesheetElement() {
|
|
1221
1439
|
const element = document.createElement("style");
|
|
1222
1440
|
element.type = "text/css";
|
|
1223
1441
|
element.textContent = ProgressBar.defaultCSS;
|
|
1442
|
+
if (this.cspNonce) {
|
|
1443
|
+
element.nonce = this.cspNonce;
|
|
1444
|
+
}
|
|
1224
1445
|
return element;
|
|
1225
1446
|
}
|
|
1226
1447
|
createProgressElement() {
|
|
@@ -1228,6 +1449,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1228
1449
|
element.className = "turbo-progress-bar";
|
|
1229
1450
|
return element;
|
|
1230
1451
|
}
|
|
1452
|
+
get cspNonce() {
|
|
1453
|
+
return getMetaContent("csp-nonce");
|
|
1454
|
+
}
|
|
1231
1455
|
}
|
|
1232
1456
|
ProgressBar.animationDuration = 300;
|
|
1233
1457
|
|
|
@@ -1244,14 +1468,14 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1244
1468
|
: {
|
|
1245
1469
|
type: elementType(element),
|
|
1246
1470
|
tracked: elementIsTracked(element),
|
|
1247
|
-
elements: []
|
|
1471
|
+
elements: [],
|
|
1248
1472
|
};
|
|
1249
1473
|
return Object.assign(Object.assign({}, result), { [outerHTML]: Object.assign(Object.assign({}, details), { elements: [...details.elements, element] }) });
|
|
1250
1474
|
}, {});
|
|
1251
1475
|
}
|
|
1252
1476
|
get trackedElementSignature() {
|
|
1253
1477
|
return Object.keys(this.detailsByOuterHTML)
|
|
1254
|
-
.filter(outerHTML => this.detailsByOuterHTML[outerHTML].tracked)
|
|
1478
|
+
.filter((outerHTML) => this.detailsByOuterHTML[outerHTML].tracked)
|
|
1255
1479
|
.join("");
|
|
1256
1480
|
}
|
|
1257
1481
|
getScriptElementsNotInSnapshot(snapshot) {
|
|
@@ -1262,8 +1486,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1262
1486
|
}
|
|
1263
1487
|
getElementsMatchingTypeNotInSnapshot(matchedType, snapshot) {
|
|
1264
1488
|
return Object.keys(this.detailsByOuterHTML)
|
|
1265
|
-
.filter(outerHTML => !(outerHTML in snapshot.detailsByOuterHTML))
|
|
1266
|
-
.map(outerHTML => this.detailsByOuterHTML[outerHTML])
|
|
1489
|
+
.filter((outerHTML) => !(outerHTML in snapshot.detailsByOuterHTML))
|
|
1490
|
+
.map((outerHTML) => this.detailsByOuterHTML[outerHTML])
|
|
1267
1491
|
.filter(({ type }) => type == matchedType)
|
|
1268
1492
|
.map(({ elements: [element] }) => element);
|
|
1269
1493
|
}
|
|
@@ -1283,13 +1507,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1283
1507
|
}
|
|
1284
1508
|
getMetaValue(name) {
|
|
1285
1509
|
const element = this.findMetaElementByName(name);
|
|
1286
|
-
return element
|
|
1287
|
-
? element.getAttribute("content")
|
|
1288
|
-
: null;
|
|
1510
|
+
return element ? element.getAttribute("content") : null;
|
|
1289
1511
|
}
|
|
1290
1512
|
findMetaElementByName(name) {
|
|
1291
1513
|
return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => {
|
|
1292
|
-
const { elements: [element] } = this.detailsByOuterHTML[outerHTML];
|
|
1514
|
+
const { elements: [element], } = this.detailsByOuterHTML[outerHTML];
|
|
1293
1515
|
return elementIsMetaElementWithName(element, name) ? element : result;
|
|
1294
1516
|
}, undefined);
|
|
1295
1517
|
}
|
|
@@ -1306,19 +1528,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1306
1528
|
return element.getAttribute("data-turbo-track") == "reload";
|
|
1307
1529
|
}
|
|
1308
1530
|
function elementIsScript(element) {
|
|
1309
|
-
const tagName = element.
|
|
1531
|
+
const tagName = element.localName;
|
|
1310
1532
|
return tagName == "script";
|
|
1311
1533
|
}
|
|
1312
1534
|
function elementIsNoscript(element) {
|
|
1313
|
-
const tagName = element.
|
|
1535
|
+
const tagName = element.localName;
|
|
1314
1536
|
return tagName == "noscript";
|
|
1315
1537
|
}
|
|
1316
1538
|
function elementIsStylesheet(element) {
|
|
1317
|
-
const tagName = element.
|
|
1539
|
+
const tagName = element.localName;
|
|
1318
1540
|
return tagName == "style" || (tagName == "link" && element.getAttribute("rel") == "stylesheet");
|
|
1319
1541
|
}
|
|
1320
1542
|
function elementIsMetaElementWithName(element, name) {
|
|
1321
|
-
const tagName = element.
|
|
1543
|
+
const tagName = element.localName;
|
|
1322
1544
|
return tagName == "meta" && element.getAttribute("name") == name;
|
|
1323
1545
|
}
|
|
1324
1546
|
function elementWithoutNonce(element) {
|
|
@@ -1343,7 +1565,20 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1343
1565
|
return new this(body, new HeadSnapshot(head));
|
|
1344
1566
|
}
|
|
1345
1567
|
clone() {
|
|
1346
|
-
|
|
1568
|
+
const clonedElement = this.element.cloneNode(true);
|
|
1569
|
+
const selectElements = this.element.querySelectorAll("select");
|
|
1570
|
+
const clonedSelectElements = clonedElement.querySelectorAll("select");
|
|
1571
|
+
for (const [index, source] of selectElements.entries()) {
|
|
1572
|
+
const clone = clonedSelectElements[index];
|
|
1573
|
+
for (const option of clone.selectedOptions)
|
|
1574
|
+
option.selected = false;
|
|
1575
|
+
for (const option of source.selectedOptions)
|
|
1576
|
+
clone.options[option.index].selected = true;
|
|
1577
|
+
}
|
|
1578
|
+
for (const clonedPasswordInput of clonedElement.querySelectorAll('input[type="password"]')) {
|
|
1579
|
+
clonedPasswordInput.value = "";
|
|
1580
|
+
}
|
|
1581
|
+
return new PageSnapshot(clonedElement, this.headSnapshot);
|
|
1347
1582
|
}
|
|
1348
1583
|
get headElement() {
|
|
1349
1584
|
return this.headSnapshot.element;
|
|
@@ -1390,6 +1625,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1390
1625
|
historyChanged: false,
|
|
1391
1626
|
visitCachedSnapshot: () => { },
|
|
1392
1627
|
willRender: true,
|
|
1628
|
+
updateHistory: true,
|
|
1629
|
+
shouldCacheSnapshot: true,
|
|
1630
|
+
acceptsStreamResponse: false,
|
|
1631
|
+
initiator: document.documentElement,
|
|
1393
1632
|
};
|
|
1394
1633
|
var SystemStatusCode;
|
|
1395
1634
|
(function (SystemStatusCode) {
|
|
@@ -1399,17 +1638,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1399
1638
|
})(SystemStatusCode || (SystemStatusCode = {}));
|
|
1400
1639
|
class Visit {
|
|
1401
1640
|
constructor(delegate, location, restorationIdentifier, options = {}) {
|
|
1402
|
-
this.identifier = uuid();
|
|
1403
1641
|
this.timingMetrics = {};
|
|
1404
1642
|
this.followedRedirect = false;
|
|
1405
1643
|
this.historyChanged = false;
|
|
1406
1644
|
this.scrolled = false;
|
|
1645
|
+
this.shouldCacheSnapshot = true;
|
|
1646
|
+
this.acceptsStreamResponse = false;
|
|
1407
1647
|
this.snapshotCached = false;
|
|
1408
1648
|
this.state = VisitState.initialized;
|
|
1409
1649
|
this.delegate = delegate;
|
|
1410
1650
|
this.location = location;
|
|
1411
1651
|
this.restorationIdentifier = restorationIdentifier || uuid();
|
|
1412
|
-
|
|
1652
|
+
this.promise = new Promise((resolve, reject) => (this.resolvingFunctions = { resolve, reject }));
|
|
1653
|
+
const { action, historyChanged, referrer, snapshotHTML, response, visitCachedSnapshot, willRender, updateHistory, shouldCacheSnapshot, acceptsStreamResponse, initiator, } = Object.assign(Object.assign({}, defaultOptions), options);
|
|
1413
1654
|
this.action = action;
|
|
1414
1655
|
this.historyChanged = historyChanged;
|
|
1415
1656
|
this.referrer = referrer;
|
|
@@ -1418,7 +1659,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1418
1659
|
this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action);
|
|
1419
1660
|
this.visitCachedSnapshot = visitCachedSnapshot;
|
|
1420
1661
|
this.willRender = willRender;
|
|
1662
|
+
this.updateHistory = updateHistory;
|
|
1421
1663
|
this.scrolled = !willRender;
|
|
1664
|
+
this.shouldCacheSnapshot = shouldCacheSnapshot;
|
|
1665
|
+
this.acceptsStreamResponse = acceptsStreamResponse;
|
|
1666
|
+
this.initiator = initiator;
|
|
1422
1667
|
}
|
|
1423
1668
|
get adapter() {
|
|
1424
1669
|
return this.delegate.adapter;
|
|
@@ -1450,28 +1695,33 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1450
1695
|
}
|
|
1451
1696
|
this.cancelRender();
|
|
1452
1697
|
this.state = VisitState.canceled;
|
|
1698
|
+
this.resolvingFunctions.reject();
|
|
1453
1699
|
}
|
|
1454
1700
|
}
|
|
1455
1701
|
complete() {
|
|
1456
1702
|
if (this.state == VisitState.started) {
|
|
1457
1703
|
this.recordTimingMetric(TimingMetric.visitEnd);
|
|
1458
1704
|
this.state = VisitState.completed;
|
|
1459
|
-
this.adapter.visitCompleted(this);
|
|
1460
|
-
this.delegate.visitCompleted(this);
|
|
1461
1705
|
this.followRedirect();
|
|
1706
|
+
if (!this.followedRedirect) {
|
|
1707
|
+
this.adapter.visitCompleted(this);
|
|
1708
|
+
this.delegate.visitCompleted(this);
|
|
1709
|
+
}
|
|
1710
|
+
this.resolvingFunctions.resolve();
|
|
1462
1711
|
}
|
|
1463
1712
|
}
|
|
1464
1713
|
fail() {
|
|
1465
1714
|
if (this.state == VisitState.started) {
|
|
1466
1715
|
this.state = VisitState.failed;
|
|
1467
1716
|
this.adapter.visitFailed(this);
|
|
1717
|
+
this.resolvingFunctions.reject();
|
|
1468
1718
|
}
|
|
1469
1719
|
}
|
|
1470
1720
|
changeHistory() {
|
|
1471
1721
|
var _a;
|
|
1472
|
-
if (!this.historyChanged) {
|
|
1722
|
+
if (!this.historyChanged && this.updateHistory) {
|
|
1473
1723
|
const actionForHistory = this.location.href === ((_a = this.referrer) === null || _a === void 0 ? void 0 : _a.href) ? "replace" : this.action;
|
|
1474
|
-
const method =
|
|
1724
|
+
const method = getHistoryMethodForAction(actionForHistory);
|
|
1475
1725
|
this.history.update(method, this.location, this.restorationIdentifier);
|
|
1476
1726
|
this.historyChanged = true;
|
|
1477
1727
|
}
|
|
@@ -1481,7 +1731,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1481
1731
|
this.simulateRequest();
|
|
1482
1732
|
}
|
|
1483
1733
|
else if (this.shouldIssueRequest() && !this.request) {
|
|
1484
|
-
this.request = new FetchRequest(this, FetchMethod.get, this.location);
|
|
1734
|
+
this.request = new FetchRequest(this, FetchMethod.get, this.location, undefined, this.initiator);
|
|
1485
1735
|
this.request.perform();
|
|
1486
1736
|
}
|
|
1487
1737
|
}
|
|
@@ -1516,16 +1766,18 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1516
1766
|
if (this.response) {
|
|
1517
1767
|
const { statusCode, responseHTML } = this.response;
|
|
1518
1768
|
this.render(async () => {
|
|
1519
|
-
this.
|
|
1769
|
+
if (this.shouldCacheSnapshot)
|
|
1770
|
+
this.cacheSnapshot();
|
|
1520
1771
|
if (this.view.renderPromise)
|
|
1521
1772
|
await this.view.renderPromise;
|
|
1522
1773
|
if (isSuccessful(statusCode) && responseHTML != null) {
|
|
1523
|
-
await this.view.renderPage(PageSnapshot.fromHTMLString(responseHTML), false, this.willRender);
|
|
1774
|
+
await this.view.renderPage(PageSnapshot.fromHTMLString(responseHTML), false, this.willRender, this);
|
|
1775
|
+
this.performScroll();
|
|
1524
1776
|
this.adapter.visitRendered(this);
|
|
1525
1777
|
this.complete();
|
|
1526
1778
|
}
|
|
1527
1779
|
else {
|
|
1528
|
-
await this.view.renderError(PageSnapshot.fromHTMLString(responseHTML));
|
|
1780
|
+
await this.view.renderError(PageSnapshot.fromHTMLString(responseHTML), this);
|
|
1529
1781
|
this.adapter.visitRendered(this);
|
|
1530
1782
|
this.fail();
|
|
1531
1783
|
}
|
|
@@ -1560,7 +1812,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1560
1812
|
else {
|
|
1561
1813
|
if (this.view.renderPromise)
|
|
1562
1814
|
await this.view.renderPromise;
|
|
1563
|
-
await this.view.renderPage(snapshot, isPreview, this.willRender);
|
|
1815
|
+
await this.view.renderPage(snapshot, isPreview, this.willRender, this);
|
|
1816
|
+
this.performScroll();
|
|
1564
1817
|
this.adapter.visitRendered(this);
|
|
1565
1818
|
if (!isPreview) {
|
|
1566
1819
|
this.complete();
|
|
@@ -1573,8 +1826,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1573
1826
|
var _a;
|
|
1574
1827
|
if (this.redirectedToLocation && !this.followedRedirect && ((_a = this.response) === null || _a === void 0 ? void 0 : _a.redirected)) {
|
|
1575
1828
|
this.adapter.visitProposedToLocation(this.redirectedToLocation, {
|
|
1576
|
-
action:
|
|
1577
|
-
response: this.response
|
|
1829
|
+
action: "replace",
|
|
1830
|
+
response: this.response,
|
|
1578
1831
|
});
|
|
1579
1832
|
this.followedRedirect = true;
|
|
1580
1833
|
}
|
|
@@ -1583,20 +1836,28 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1583
1836
|
if (this.isSamePage) {
|
|
1584
1837
|
this.render(async () => {
|
|
1585
1838
|
this.cacheSnapshot();
|
|
1839
|
+
this.performScroll();
|
|
1586
1840
|
this.adapter.visitRendered(this);
|
|
1587
1841
|
});
|
|
1588
1842
|
}
|
|
1589
1843
|
}
|
|
1844
|
+
prepareHeadersForRequest(headers, request) {
|
|
1845
|
+
if (this.acceptsStreamResponse) {
|
|
1846
|
+
request.acceptResponseType(StreamMessage.contentType);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1590
1849
|
requestStarted() {
|
|
1591
1850
|
this.startRequest();
|
|
1592
1851
|
}
|
|
1593
|
-
requestPreventedHandlingResponse(
|
|
1594
|
-
}
|
|
1852
|
+
requestPreventedHandlingResponse(_request, _response) { }
|
|
1595
1853
|
async requestSucceededWithResponse(request, response) {
|
|
1596
1854
|
const responseHTML = await response.responseHTML;
|
|
1597
1855
|
const { redirected, statusCode } = response;
|
|
1598
1856
|
if (responseHTML == undefined) {
|
|
1599
|
-
this.recordResponse({
|
|
1857
|
+
this.recordResponse({
|
|
1858
|
+
statusCode: SystemStatusCode.contentTypeMismatch,
|
|
1859
|
+
redirected,
|
|
1860
|
+
});
|
|
1600
1861
|
}
|
|
1601
1862
|
else {
|
|
1602
1863
|
this.redirectedToLocation = response.redirected ? response.location : undefined;
|
|
@@ -1607,20 +1868,26 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1607
1868
|
const responseHTML = await response.responseHTML;
|
|
1608
1869
|
const { redirected, statusCode } = response;
|
|
1609
1870
|
if (responseHTML == undefined) {
|
|
1610
|
-
this.recordResponse({
|
|
1871
|
+
this.recordResponse({
|
|
1872
|
+
statusCode: SystemStatusCode.contentTypeMismatch,
|
|
1873
|
+
redirected,
|
|
1874
|
+
});
|
|
1611
1875
|
}
|
|
1612
1876
|
else {
|
|
1613
1877
|
this.recordResponse({ statusCode: statusCode, responseHTML, redirected });
|
|
1614
1878
|
}
|
|
1615
1879
|
}
|
|
1616
|
-
requestErrored(
|
|
1617
|
-
this.recordResponse({
|
|
1880
|
+
requestErrored(_request, _error) {
|
|
1881
|
+
this.recordResponse({
|
|
1882
|
+
statusCode: SystemStatusCode.networkFailure,
|
|
1883
|
+
redirected: false,
|
|
1884
|
+
});
|
|
1618
1885
|
}
|
|
1619
1886
|
requestFinished() {
|
|
1620
1887
|
this.finishRequest();
|
|
1621
1888
|
}
|
|
1622
1889
|
performScroll() {
|
|
1623
|
-
if (!this.scrolled) {
|
|
1890
|
+
if (!this.scrolled && !this.view.forceReloaded) {
|
|
1624
1891
|
if (this.action == "restore") {
|
|
1625
1892
|
this.scrollToRestoredPosition() || this.scrollToAnchor() || this.view.scrollToTop();
|
|
1626
1893
|
}
|
|
@@ -1655,9 +1922,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1655
1922
|
}
|
|
1656
1923
|
getHistoryMethodForAction(action) {
|
|
1657
1924
|
switch (action) {
|
|
1658
|
-
case "replace":
|
|
1925
|
+
case "replace":
|
|
1926
|
+
return history.replaceState;
|
|
1659
1927
|
case "advance":
|
|
1660
|
-
case "restore":
|
|
1928
|
+
case "restore":
|
|
1929
|
+
return history.pushState;
|
|
1661
1930
|
}
|
|
1662
1931
|
}
|
|
1663
1932
|
hasPreloadedResponse() {
|
|
@@ -1676,18 +1945,17 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1676
1945
|
}
|
|
1677
1946
|
cacheSnapshot() {
|
|
1678
1947
|
if (!this.snapshotCached) {
|
|
1679
|
-
this.view.cacheSnapshot().then(snapshot => snapshot && this.visitCachedSnapshot(snapshot));
|
|
1948
|
+
this.view.cacheSnapshot().then((snapshot) => snapshot && this.visitCachedSnapshot(snapshot));
|
|
1680
1949
|
this.snapshotCached = true;
|
|
1681
1950
|
}
|
|
1682
1951
|
}
|
|
1683
1952
|
async render(callback) {
|
|
1684
1953
|
this.cancelRender();
|
|
1685
|
-
await new Promise(resolve => {
|
|
1954
|
+
await new Promise((resolve) => {
|
|
1686
1955
|
this.frame = requestAnimationFrame(() => resolve());
|
|
1687
1956
|
});
|
|
1688
1957
|
await callback();
|
|
1689
1958
|
delete this.frame;
|
|
1690
|
-
this.performScroll();
|
|
1691
1959
|
}
|
|
1692
1960
|
cancelRender() {
|
|
1693
1961
|
if (this.frame) {
|
|
@@ -1702,19 +1970,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1702
1970
|
|
|
1703
1971
|
class BrowserAdapter {
|
|
1704
1972
|
constructor(session) {
|
|
1705
|
-
this.progressBar = new ProgressBar;
|
|
1973
|
+
this.progressBar = new ProgressBar();
|
|
1706
1974
|
this.showProgressBar = () => {
|
|
1707
1975
|
this.progressBar.show();
|
|
1708
1976
|
};
|
|
1709
1977
|
this.session = session;
|
|
1710
1978
|
}
|
|
1711
1979
|
visitProposedToLocation(location, options) {
|
|
1712
|
-
this.navigator.startVisit(location, uuid(), options);
|
|
1980
|
+
return this.navigator.startVisit(location, (options === null || options === void 0 ? void 0 : options.restorationIdentifier) || uuid(), options);
|
|
1713
1981
|
}
|
|
1714
1982
|
visitStarted(visit) {
|
|
1983
|
+
this.location = visit.location;
|
|
1715
1984
|
visit.loadCachedSnapshot();
|
|
1716
1985
|
visit.issueRequest();
|
|
1717
|
-
visit.changeHistory();
|
|
1718
1986
|
visit.goToSamePageAnchor();
|
|
1719
1987
|
}
|
|
1720
1988
|
visitRequestStarted(visit) {
|
|
@@ -1734,29 +2002,31 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1734
2002
|
case SystemStatusCode.networkFailure:
|
|
1735
2003
|
case SystemStatusCode.timeoutFailure:
|
|
1736
2004
|
case SystemStatusCode.contentTypeMismatch:
|
|
1737
|
-
return this.reload(
|
|
2005
|
+
return this.reload({
|
|
2006
|
+
reason: "request_failed",
|
|
2007
|
+
context: {
|
|
2008
|
+
statusCode,
|
|
2009
|
+
},
|
|
2010
|
+
});
|
|
1738
2011
|
default:
|
|
1739
2012
|
return visit.loadResponse();
|
|
1740
2013
|
}
|
|
1741
2014
|
}
|
|
1742
|
-
visitRequestFinished(
|
|
2015
|
+
visitRequestFinished(_visit) {
|
|
1743
2016
|
this.progressBar.setValue(1);
|
|
1744
2017
|
this.hideVisitProgressBar();
|
|
1745
2018
|
}
|
|
1746
|
-
visitCompleted(
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
this.reload();
|
|
1750
|
-
}
|
|
1751
|
-
visitFailed(visit) {
|
|
2019
|
+
visitCompleted(_visit) { }
|
|
2020
|
+
pageInvalidated(reason) {
|
|
2021
|
+
this.reload(reason);
|
|
1752
2022
|
}
|
|
1753
|
-
|
|
1754
|
-
}
|
|
1755
|
-
formSubmissionStarted(
|
|
2023
|
+
visitFailed(_visit) { }
|
|
2024
|
+
visitRendered(_visit) { }
|
|
2025
|
+
formSubmissionStarted(_formSubmission) {
|
|
1756
2026
|
this.progressBar.setValue(0);
|
|
1757
2027
|
this.showFormProgressBarAfterDelay();
|
|
1758
2028
|
}
|
|
1759
|
-
formSubmissionFinished(
|
|
2029
|
+
formSubmissionFinished(_formSubmission) {
|
|
1760
2030
|
this.progressBar.setValue(1);
|
|
1761
2031
|
this.hideFormProgressBar();
|
|
1762
2032
|
}
|
|
@@ -1782,8 +2052,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1782
2052
|
delete this.formProgressBarTimeout;
|
|
1783
2053
|
}
|
|
1784
2054
|
}
|
|
1785
|
-
reload() {
|
|
1786
|
-
|
|
2055
|
+
reload(reason) {
|
|
2056
|
+
dispatch("turbo:reload", { detail: reason });
|
|
2057
|
+
if (!this.location)
|
|
2058
|
+
return;
|
|
2059
|
+
window.location.href = this.location.toString();
|
|
1787
2060
|
}
|
|
1788
2061
|
get navigator() {
|
|
1789
2062
|
return this.session.navigator;
|
|
@@ -1793,94 +2066,60 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1793
2066
|
class CacheObserver {
|
|
1794
2067
|
constructor() {
|
|
1795
2068
|
this.started = false;
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
addEventListener("turbo:before-cache", this.removeStaleElements, false);
|
|
1801
|
-
}
|
|
1802
|
-
}
|
|
1803
|
-
stop() {
|
|
1804
|
-
if (this.started) {
|
|
1805
|
-
this.started = false;
|
|
1806
|
-
removeEventListener("turbo:before-cache", this.removeStaleElements, false);
|
|
1807
|
-
}
|
|
1808
|
-
}
|
|
1809
|
-
removeStaleElements() {
|
|
1810
|
-
const staleElements = [...document.querySelectorAll('[data-turbo-cache="false"]')];
|
|
1811
|
-
for (const element of staleElements) {
|
|
1812
|
-
element.remove();
|
|
1813
|
-
}
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
|
|
1817
|
-
class FormSubmitObserver {
|
|
1818
|
-
constructor(delegate) {
|
|
1819
|
-
this.started = false;
|
|
1820
|
-
this.submitCaptured = () => {
|
|
1821
|
-
removeEventListener("submit", this.submitBubbled, false);
|
|
1822
|
-
addEventListener("submit", this.submitBubbled, false);
|
|
1823
|
-
};
|
|
1824
|
-
this.submitBubbled = ((event) => {
|
|
1825
|
-
if (!event.defaultPrevented) {
|
|
1826
|
-
const form = event.target instanceof HTMLFormElement ? event.target : undefined;
|
|
1827
|
-
const submitter = event.submitter || undefined;
|
|
1828
|
-
if (form) {
|
|
1829
|
-
const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.getAttribute("method");
|
|
1830
|
-
if (method != "dialog" && this.delegate.willSubmitForm(form, submitter)) {
|
|
1831
|
-
event.preventDefault();
|
|
1832
|
-
this.delegate.formSubmitted(form, submitter);
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
2069
|
+
this.removeStaleElements = ((_event) => {
|
|
2070
|
+
const staleElements = [...document.querySelectorAll('[data-turbo-cache="false"]')];
|
|
2071
|
+
for (const element of staleElements) {
|
|
2072
|
+
element.remove();
|
|
1835
2073
|
}
|
|
1836
2074
|
});
|
|
1837
|
-
this.delegate = delegate;
|
|
1838
2075
|
}
|
|
1839
2076
|
start() {
|
|
1840
2077
|
if (!this.started) {
|
|
1841
|
-
addEventListener("submit", this.submitCaptured, true);
|
|
1842
2078
|
this.started = true;
|
|
2079
|
+
addEventListener("turbo:before-cache", this.removeStaleElements, false);
|
|
1843
2080
|
}
|
|
1844
2081
|
}
|
|
1845
2082
|
stop() {
|
|
1846
2083
|
if (this.started) {
|
|
1847
|
-
removeEventListener("submit", this.submitCaptured, true);
|
|
1848
2084
|
this.started = false;
|
|
2085
|
+
removeEventListener("turbo:before-cache", this.removeStaleElements, false);
|
|
1849
2086
|
}
|
|
1850
2087
|
}
|
|
1851
2088
|
}
|
|
1852
2089
|
|
|
1853
2090
|
class FrameRedirector {
|
|
1854
|
-
constructor(element) {
|
|
2091
|
+
constructor(session, element) {
|
|
2092
|
+
this.session = session;
|
|
1855
2093
|
this.element = element;
|
|
1856
|
-
this.
|
|
1857
|
-
this.
|
|
2094
|
+
this.linkClickObserver = new LinkClickObserver(this, element);
|
|
2095
|
+
this.formSubmitObserver = new FormSubmitObserver(this, element);
|
|
1858
2096
|
}
|
|
1859
2097
|
start() {
|
|
1860
|
-
this.
|
|
1861
|
-
this.
|
|
2098
|
+
this.linkClickObserver.start();
|
|
2099
|
+
this.formSubmitObserver.start();
|
|
1862
2100
|
}
|
|
1863
2101
|
stop() {
|
|
1864
|
-
this.
|
|
1865
|
-
this.
|
|
2102
|
+
this.linkClickObserver.stop();
|
|
2103
|
+
this.formSubmitObserver.stop();
|
|
1866
2104
|
}
|
|
1867
|
-
|
|
2105
|
+
willFollowLinkToLocation(element) {
|
|
1868
2106
|
return this.shouldRedirect(element);
|
|
1869
2107
|
}
|
|
1870
|
-
|
|
2108
|
+
followedLinkToLocation(element, url) {
|
|
1871
2109
|
const frame = this.findFrameElement(element);
|
|
1872
2110
|
if (frame) {
|
|
1873
|
-
frame.delegate.
|
|
2111
|
+
frame.delegate.followedLinkToLocation(element, url);
|
|
1874
2112
|
}
|
|
1875
2113
|
}
|
|
1876
|
-
|
|
1877
|
-
return
|
|
2114
|
+
willSubmitForm(element, submitter) {
|
|
2115
|
+
return (element.closest("turbo-frame") == null &&
|
|
2116
|
+
this.shouldSubmit(element, submitter) &&
|
|
2117
|
+
this.shouldRedirect(element, submitter));
|
|
1878
2118
|
}
|
|
1879
|
-
|
|
2119
|
+
formSubmitted(element, submitter) {
|
|
1880
2120
|
const frame = this.findFrameElement(element, submitter);
|
|
1881
2121
|
if (frame) {
|
|
1882
|
-
frame.
|
|
1883
|
-
frame.delegate.formSubmissionIntercepted(element, submitter);
|
|
2122
|
+
frame.delegate.formSubmitted(element, submitter);
|
|
1884
2123
|
}
|
|
1885
2124
|
}
|
|
1886
2125
|
shouldSubmit(form, submitter) {
|
|
@@ -1891,8 +2130,16 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1891
2130
|
return this.shouldRedirect(form, submitter) && locationIsVisitable(action, rootLocation);
|
|
1892
2131
|
}
|
|
1893
2132
|
shouldRedirect(element, submitter) {
|
|
1894
|
-
const
|
|
1895
|
-
|
|
2133
|
+
const isNavigatable = element instanceof HTMLFormElement
|
|
2134
|
+
? this.session.submissionIsNavigatable(element, submitter)
|
|
2135
|
+
: this.session.elementIsNavigatable(element);
|
|
2136
|
+
if (isNavigatable) {
|
|
2137
|
+
const frame = this.findFrameElement(element, submitter);
|
|
2138
|
+
return frame ? frame != element.closest("turbo-frame") : false;
|
|
2139
|
+
}
|
|
2140
|
+
else {
|
|
2141
|
+
return false;
|
|
2142
|
+
}
|
|
1896
2143
|
}
|
|
1897
2144
|
findFrameElement(element, submitter) {
|
|
1898
2145
|
const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame");
|
|
@@ -1922,7 +2169,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1922
2169
|
}
|
|
1923
2170
|
}
|
|
1924
2171
|
};
|
|
1925
|
-
this.onPageLoad = async (
|
|
2172
|
+
this.onPageLoad = async (_event) => {
|
|
1926
2173
|
await nextMicrotask();
|
|
1927
2174
|
this.pageLoaded = true;
|
|
1928
2175
|
};
|
|
@@ -1984,81 +2231,30 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1984
2231
|
}
|
|
1985
2232
|
}
|
|
1986
2233
|
|
|
1987
|
-
class
|
|
1988
|
-
constructor(delegate) {
|
|
1989
|
-
this.started = false;
|
|
1990
|
-
this.clickCaptured = () => {
|
|
1991
|
-
removeEventListener("click", this.clickBubbled, false);
|
|
1992
|
-
addEventListener("click", this.clickBubbled, false);
|
|
1993
|
-
};
|
|
1994
|
-
this.clickBubbled = (event) => {
|
|
1995
|
-
if (this.clickEventIsSignificant(event)) {
|
|
1996
|
-
const target = (event.composedPath && event.composedPath()[0]) || event.target;
|
|
1997
|
-
const link = this.findLinkFromClickTarget(target);
|
|
1998
|
-
if (link) {
|
|
1999
|
-
const location = this.getLocationForLink(link);
|
|
2000
|
-
if (this.delegate.willFollowLinkToLocation(link, location)) {
|
|
2001
|
-
event.preventDefault();
|
|
2002
|
-
this.delegate.followedLinkToLocation(link, location);
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
}
|
|
2006
|
-
};
|
|
2007
|
-
this.delegate = delegate;
|
|
2008
|
-
}
|
|
2009
|
-
start() {
|
|
2010
|
-
if (!this.started) {
|
|
2011
|
-
addEventListener("click", this.clickCaptured, true);
|
|
2012
|
-
this.started = true;
|
|
2013
|
-
}
|
|
2014
|
-
}
|
|
2015
|
-
stop() {
|
|
2016
|
-
if (this.started) {
|
|
2017
|
-
removeEventListener("click", this.clickCaptured, true);
|
|
2018
|
-
this.started = false;
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
clickEventIsSignificant(event) {
|
|
2022
|
-
return !((event.target && event.target.isContentEditable)
|
|
2023
|
-
|| event.defaultPrevented
|
|
2024
|
-
|| event.which > 1
|
|
2025
|
-
|| event.altKey
|
|
2026
|
-
|| event.ctrlKey
|
|
2027
|
-
|| event.metaKey
|
|
2028
|
-
|| event.shiftKey);
|
|
2029
|
-
}
|
|
2030
|
-
findLinkFromClickTarget(target) {
|
|
2031
|
-
if (target instanceof Element) {
|
|
2032
|
-
return target.closest("a[href]:not([target^=_]):not([download])");
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2035
|
-
getLocationForLink(link) {
|
|
2036
|
-
return expandURL(link.getAttribute("href") || "");
|
|
2037
|
-
}
|
|
2038
|
-
}
|
|
2039
|
-
|
|
2040
|
-
function isAction(action) {
|
|
2041
|
-
return action == "advance" || action == "replace" || action == "restore";
|
|
2042
|
-
}
|
|
2043
|
-
|
|
2044
|
-
class Navigator {
|
|
2234
|
+
class Navigator {
|
|
2045
2235
|
constructor(delegate) {
|
|
2046
2236
|
this.delegate = delegate;
|
|
2047
2237
|
}
|
|
2048
2238
|
proposeVisit(location, options = {}) {
|
|
2049
|
-
if (this.delegate.
|
|
2239
|
+
if (this.delegate.allowsVisitingLocation(location, options)) {
|
|
2050
2240
|
if (locationIsVisitable(location, this.view.snapshot.rootLocation)) {
|
|
2051
|
-
this.delegate.visitProposedToLocation(location, options);
|
|
2241
|
+
return this.delegate.visitProposedToLocation(location, options);
|
|
2052
2242
|
}
|
|
2053
2243
|
else {
|
|
2054
2244
|
window.location.href = location.toString();
|
|
2245
|
+
return Promise.resolve();
|
|
2055
2246
|
}
|
|
2056
2247
|
}
|
|
2248
|
+
else {
|
|
2249
|
+
return Promise.reject();
|
|
2250
|
+
}
|
|
2057
2251
|
}
|
|
2058
2252
|
startVisit(locatable, restorationIdentifier, options = {}) {
|
|
2253
|
+
this.lastVisit = this.currentVisit;
|
|
2059
2254
|
this.stop();
|
|
2060
2255
|
this.currentVisit = new Visit(this, expandURL(locatable), restorationIdentifier, Object.assign({ referrer: this.location }, options));
|
|
2061
2256
|
this.currentVisit.start();
|
|
2257
|
+
return this.currentVisit.promise;
|
|
2062
2258
|
}
|
|
2063
2259
|
submitForm(form, submitter) {
|
|
2064
2260
|
this.stop();
|
|
@@ -2085,7 +2281,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2085
2281
|
return this.delegate.history;
|
|
2086
2282
|
}
|
|
2087
2283
|
formSubmissionStarted(formSubmission) {
|
|
2088
|
-
if (typeof this.adapter.formSubmissionStarted ===
|
|
2284
|
+
if (typeof this.adapter.formSubmissionStarted === "function") {
|
|
2089
2285
|
this.adapter.formSubmissionStarted(formSubmission);
|
|
2090
2286
|
}
|
|
2091
2287
|
}
|
|
@@ -2093,12 +2289,17 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2093
2289
|
if (formSubmission == this.formSubmission) {
|
|
2094
2290
|
const responseHTML = await fetchResponse.responseHTML;
|
|
2095
2291
|
if (responseHTML) {
|
|
2096
|
-
|
|
2292
|
+
const shouldCacheSnapshot = formSubmission.method == FetchMethod.get;
|
|
2293
|
+
if (!shouldCacheSnapshot) {
|
|
2097
2294
|
this.view.clearSnapshotCache();
|
|
2098
2295
|
}
|
|
2099
2296
|
const { statusCode, redirected } = fetchResponse;
|
|
2100
2297
|
const action = this.getActionForFormSubmission(formSubmission);
|
|
2101
|
-
const visitOptions = {
|
|
2298
|
+
const visitOptions = {
|
|
2299
|
+
action,
|
|
2300
|
+
shouldCacheSnapshot,
|
|
2301
|
+
response: { statusCode, responseHTML, redirected },
|
|
2302
|
+
};
|
|
2102
2303
|
this.proposeVisit(fetchResponse.location, visitOptions);
|
|
2103
2304
|
}
|
|
2104
2305
|
}
|
|
@@ -2108,10 +2309,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2108
2309
|
if (responseHTML) {
|
|
2109
2310
|
const snapshot = PageSnapshot.fromHTMLString(responseHTML);
|
|
2110
2311
|
if (fetchResponse.serverError) {
|
|
2111
|
-
await this.view.renderError(snapshot);
|
|
2312
|
+
await this.view.renderError(snapshot, this.currentVisit);
|
|
2112
2313
|
}
|
|
2113
2314
|
else {
|
|
2114
|
-
await this.view.renderPage(snapshot);
|
|
2315
|
+
await this.view.renderPage(snapshot, false, true, this.currentVisit);
|
|
2115
2316
|
}
|
|
2116
2317
|
this.view.scrollToTop();
|
|
2117
2318
|
this.view.clearSnapshotCache();
|
|
@@ -2121,7 +2322,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2121
2322
|
console.error(error);
|
|
2122
2323
|
}
|
|
2123
2324
|
formSubmissionFinished(formSubmission) {
|
|
2124
|
-
if (typeof this.adapter.formSubmissionFinished ===
|
|
2325
|
+
if (typeof this.adapter.formSubmissionFinished === "function") {
|
|
2125
2326
|
this.adapter.formSubmissionFinished(formSubmission);
|
|
2126
2327
|
}
|
|
2127
2328
|
}
|
|
@@ -2132,12 +2333,14 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2132
2333
|
this.delegate.visitCompleted(visit);
|
|
2133
2334
|
}
|
|
2134
2335
|
locationWithActionIsSamePage(location, action) {
|
|
2336
|
+
var _a;
|
|
2135
2337
|
const anchor = getAnchor(location);
|
|
2136
|
-
const
|
|
2137
|
-
const
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
(
|
|
2338
|
+
const lastLocation = ((_a = this.lastVisit) === null || _a === void 0 ? void 0 : _a.location) || this.view.lastRenderedLocation;
|
|
2339
|
+
const currentAnchor = getAnchor(lastLocation);
|
|
2340
|
+
const isRestorationToTop = action === "restore" && typeof anchor === "undefined";
|
|
2341
|
+
return (action !== "replace" &&
|
|
2342
|
+
getRequestURL(location) === getRequestURL(lastLocation) &&
|
|
2343
|
+
(isRestorationToTop || (anchor != null && anchor !== currentAnchor)));
|
|
2141
2344
|
}
|
|
2142
2345
|
visitScrolledToSamePageLocation(oldURL, newURL) {
|
|
2143
2346
|
this.delegate.visitScrolledToSamePageLocation(oldURL, newURL);
|
|
@@ -2241,9 +2444,33 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2241
2444
|
}
|
|
2242
2445
|
}
|
|
2243
2446
|
|
|
2447
|
+
class StreamMessageRenderer {
|
|
2448
|
+
render({ fragment }) {
|
|
2449
|
+
Bardo.preservingPermanentElements(this, getPermanentElementMapForFragment(fragment), () => document.documentElement.appendChild(fragment));
|
|
2450
|
+
}
|
|
2451
|
+
enteringBardo(currentPermanentElement, newPermanentElement) {
|
|
2452
|
+
newPermanentElement.replaceWith(currentPermanentElement.cloneNode(true));
|
|
2453
|
+
}
|
|
2454
|
+
leavingBardo() { }
|
|
2455
|
+
}
|
|
2456
|
+
function getPermanentElementMapForFragment(fragment) {
|
|
2457
|
+
const permanentElementsInDocument = queryPermanentElementsAll(document.documentElement);
|
|
2458
|
+
const permanentElementMap = {};
|
|
2459
|
+
for (const permanentElementInDocument of permanentElementsInDocument) {
|
|
2460
|
+
const { id } = permanentElementInDocument;
|
|
2461
|
+
for (const streamElement of fragment.querySelectorAll("turbo-stream")) {
|
|
2462
|
+
const elementInStream = getPermanentElementById(streamElement.templateElement.content, id);
|
|
2463
|
+
if (elementInStream) {
|
|
2464
|
+
permanentElementMap[id] = [permanentElementInDocument, elementInStream];
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
return permanentElementMap;
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2244
2471
|
class StreamObserver {
|
|
2245
2472
|
constructor(delegate) {
|
|
2246
|
-
this.sources = new Set;
|
|
2473
|
+
this.sources = new Set();
|
|
2247
2474
|
this.started = false;
|
|
2248
2475
|
this.inspectFetchResponse = ((event) => {
|
|
2249
2476
|
const response = fetchResponseFromEvent(event);
|
|
@@ -2293,7 +2520,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2293
2520
|
}
|
|
2294
2521
|
}
|
|
2295
2522
|
receiveMessageHTML(html) {
|
|
2296
|
-
this.delegate.receivedMessageFromStream(
|
|
2523
|
+
this.delegate.receivedMessageFromStream(StreamMessage.wrap(html));
|
|
2297
2524
|
}
|
|
2298
2525
|
}
|
|
2299
2526
|
function fetchResponseFromEvent(event) {
|
|
@@ -2310,20 +2537,24 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2310
2537
|
}
|
|
2311
2538
|
|
|
2312
2539
|
class ErrorRenderer extends Renderer {
|
|
2540
|
+
static renderElement(currentElement, newElement) {
|
|
2541
|
+
const { documentElement, body } = document;
|
|
2542
|
+
documentElement.replaceChild(newElement, body);
|
|
2543
|
+
}
|
|
2313
2544
|
async render() {
|
|
2314
2545
|
this.replaceHeadAndBody();
|
|
2315
2546
|
this.activateScriptElements();
|
|
2316
2547
|
}
|
|
2317
2548
|
replaceHeadAndBody() {
|
|
2318
|
-
const { documentElement, head
|
|
2549
|
+
const { documentElement, head } = document;
|
|
2319
2550
|
documentElement.replaceChild(this.newHead, head);
|
|
2320
|
-
|
|
2551
|
+
this.renderElement(this.currentElement, this.newElement);
|
|
2321
2552
|
}
|
|
2322
2553
|
activateScriptElements() {
|
|
2323
2554
|
for (const replaceableElement of this.scriptElements) {
|
|
2324
2555
|
const parentNode = replaceableElement.parentNode;
|
|
2325
2556
|
if (parentNode) {
|
|
2326
|
-
const element =
|
|
2557
|
+
const element = activateScriptElement(replaceableElement);
|
|
2327
2558
|
parentNode.replaceChild(element, replaceableElement);
|
|
2328
2559
|
}
|
|
2329
2560
|
}
|
|
@@ -2332,16 +2563,44 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2332
2563
|
return this.newSnapshot.headSnapshot.element;
|
|
2333
2564
|
}
|
|
2334
2565
|
get scriptElements() {
|
|
2335
|
-
return
|
|
2566
|
+
return document.documentElement.querySelectorAll("script");
|
|
2336
2567
|
}
|
|
2337
2568
|
}
|
|
2338
2569
|
|
|
2339
2570
|
class PageRenderer extends Renderer {
|
|
2571
|
+
static async renderElement(currentElement, newElement) {
|
|
2572
|
+
await nextEventLoopTick();
|
|
2573
|
+
if (document.body && newElement instanceof HTMLBodyElement) {
|
|
2574
|
+
const currentBody = PageRenderer.getBodyElement(currentElement);
|
|
2575
|
+
const newBody = PageRenderer.getBodyElement(newElement);
|
|
2576
|
+
currentBody.replaceWith(newBody);
|
|
2577
|
+
}
|
|
2578
|
+
else {
|
|
2579
|
+
document.documentElement.appendChild(newElement);
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2340
2582
|
get shouldRender() {
|
|
2341
|
-
return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical;
|
|
2583
|
+
return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical && this.bodyElementMatches;
|
|
2342
2584
|
}
|
|
2343
|
-
|
|
2344
|
-
this.
|
|
2585
|
+
get reloadReason() {
|
|
2586
|
+
if (!this.newSnapshot.isVisitable) {
|
|
2587
|
+
return {
|
|
2588
|
+
reason: "turbo_visit_control_is_reload",
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
2591
|
+
if (!this.trackedElementsAreIdentical) {
|
|
2592
|
+
return {
|
|
2593
|
+
reason: "tracked_element_mismatch",
|
|
2594
|
+
};
|
|
2595
|
+
}
|
|
2596
|
+
if (!this.bodyElementMatches) {
|
|
2597
|
+
return {
|
|
2598
|
+
reason: "body_element_mismatch",
|
|
2599
|
+
};
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
async prepareToRender() {
|
|
2603
|
+
await this.mergeHead();
|
|
2345
2604
|
}
|
|
2346
2605
|
async render() {
|
|
2347
2606
|
if (this.willRender) {
|
|
@@ -2363,11 +2622,12 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2363
2622
|
get newElement() {
|
|
2364
2623
|
return this.newSnapshot.element;
|
|
2365
2624
|
}
|
|
2366
|
-
mergeHead() {
|
|
2367
|
-
this.copyNewHeadStylesheetElements();
|
|
2625
|
+
async mergeHead() {
|
|
2626
|
+
const newStylesheetElements = this.copyNewHeadStylesheetElements();
|
|
2368
2627
|
this.copyNewHeadScriptElements();
|
|
2369
2628
|
this.removeCurrentHeadProvisionalElements();
|
|
2370
2629
|
this.copyNewHeadProvisionalElements();
|
|
2630
|
+
await newStylesheetElements;
|
|
2371
2631
|
}
|
|
2372
2632
|
replaceBody() {
|
|
2373
2633
|
this.preservingPermanentElements(() => {
|
|
@@ -2378,14 +2638,27 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2378
2638
|
get trackedElementsAreIdentical() {
|
|
2379
2639
|
return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature;
|
|
2380
2640
|
}
|
|
2381
|
-
|
|
2641
|
+
get bodyElementMatches() {
|
|
2642
|
+
return PageRenderer.getBodyElement(this.newElement) !== null;
|
|
2643
|
+
}
|
|
2644
|
+
static get bodySelector() {
|
|
2645
|
+
const bodyId = getBodyElementId();
|
|
2646
|
+
return bodyId ? `#${bodyId}` : "body";
|
|
2647
|
+
}
|
|
2648
|
+
static getBodyElement(element) {
|
|
2649
|
+
return element.querySelector(this.bodySelector) || element;
|
|
2650
|
+
}
|
|
2651
|
+
async copyNewHeadStylesheetElements() {
|
|
2652
|
+
const loadingElements = [];
|
|
2382
2653
|
for (const element of this.newHeadStylesheetElements) {
|
|
2654
|
+
loadingElements.push(waitForLoad(element));
|
|
2383
2655
|
document.head.appendChild(element);
|
|
2384
2656
|
}
|
|
2657
|
+
await Promise.all(loadingElements);
|
|
2385
2658
|
}
|
|
2386
2659
|
copyNewHeadScriptElements() {
|
|
2387
2660
|
for (const element of this.newHeadScriptElements) {
|
|
2388
|
-
document.head.appendChild(
|
|
2661
|
+
document.head.appendChild(activateScriptElement(element));
|
|
2389
2662
|
}
|
|
2390
2663
|
}
|
|
2391
2664
|
removeCurrentHeadProvisionalElements() {
|
|
@@ -2404,17 +2677,12 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2404
2677
|
}
|
|
2405
2678
|
activateNewBodyScriptElements() {
|
|
2406
2679
|
for (const inertScriptElement of this.newBodyScriptElements) {
|
|
2407
|
-
const activatedScriptElement =
|
|
2680
|
+
const activatedScriptElement = activateScriptElement(inertScriptElement);
|
|
2408
2681
|
inertScriptElement.replaceWith(activatedScriptElement);
|
|
2409
2682
|
}
|
|
2410
2683
|
}
|
|
2411
2684
|
assignNewBody() {
|
|
2412
|
-
|
|
2413
|
-
document.body.replaceWith(this.newElement);
|
|
2414
|
-
}
|
|
2415
|
-
else {
|
|
2416
|
-
document.documentElement.appendChild(this.newElement);
|
|
2417
|
-
}
|
|
2685
|
+
this.renderElement(this.currentElement, this.newElement);
|
|
2418
2686
|
}
|
|
2419
2687
|
get newHeadStylesheetElements() {
|
|
2420
2688
|
return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot);
|
|
@@ -2483,13 +2751,21 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2483
2751
|
super(...arguments);
|
|
2484
2752
|
this.snapshotCache = new SnapshotCache(10);
|
|
2485
2753
|
this.lastRenderedLocation = new URL(location.href);
|
|
2754
|
+
this.forceReloaded = false;
|
|
2486
2755
|
}
|
|
2487
|
-
renderPage(snapshot, isPreview = false, willRender = true) {
|
|
2488
|
-
const renderer = new PageRenderer(this.snapshot, snapshot, isPreview, willRender);
|
|
2756
|
+
renderPage(snapshot, isPreview = false, willRender = true, visit) {
|
|
2757
|
+
const renderer = new PageRenderer(this.snapshot, snapshot, PageRenderer.renderElement, isPreview, willRender);
|
|
2758
|
+
if (!renderer.shouldRender) {
|
|
2759
|
+
this.forceReloaded = true;
|
|
2760
|
+
}
|
|
2761
|
+
else {
|
|
2762
|
+
visit === null || visit === void 0 ? void 0 : visit.changeHistory();
|
|
2763
|
+
}
|
|
2489
2764
|
return this.render(renderer);
|
|
2490
2765
|
}
|
|
2491
|
-
renderError(snapshot) {
|
|
2492
|
-
|
|
2766
|
+
renderError(snapshot, visit) {
|
|
2767
|
+
visit === null || visit === void 0 ? void 0 : visit.changeHistory();
|
|
2768
|
+
const renderer = new ErrorRenderer(this.snapshot, snapshot, ErrorRenderer.renderElement, false);
|
|
2493
2769
|
return this.render(renderer);
|
|
2494
2770
|
}
|
|
2495
2771
|
clearSnapshotCache() {
|
|
@@ -2516,34 +2792,79 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2516
2792
|
}
|
|
2517
2793
|
}
|
|
2518
2794
|
|
|
2795
|
+
class Preloader {
|
|
2796
|
+
constructor(delegate) {
|
|
2797
|
+
this.selector = "a[data-turbo-preload]";
|
|
2798
|
+
this.delegate = delegate;
|
|
2799
|
+
}
|
|
2800
|
+
get snapshotCache() {
|
|
2801
|
+
return this.delegate.navigator.view.snapshotCache;
|
|
2802
|
+
}
|
|
2803
|
+
start() {
|
|
2804
|
+
if (document.readyState === "loading") {
|
|
2805
|
+
return document.addEventListener("DOMContentLoaded", () => {
|
|
2806
|
+
this.preloadOnLoadLinksForView(document.body);
|
|
2807
|
+
});
|
|
2808
|
+
}
|
|
2809
|
+
else {
|
|
2810
|
+
this.preloadOnLoadLinksForView(document.body);
|
|
2811
|
+
}
|
|
2812
|
+
}
|
|
2813
|
+
preloadOnLoadLinksForView(element) {
|
|
2814
|
+
for (const link of element.querySelectorAll(this.selector)) {
|
|
2815
|
+
this.preloadURL(link);
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
async preloadURL(link) {
|
|
2819
|
+
const location = new URL(link.href);
|
|
2820
|
+
if (this.snapshotCache.has(location)) {
|
|
2821
|
+
return;
|
|
2822
|
+
}
|
|
2823
|
+
try {
|
|
2824
|
+
const response = await fetch(location.toString(), { headers: { "VND.PREFETCH": "true", Accept: "text/html" } });
|
|
2825
|
+
const responseText = await response.text();
|
|
2826
|
+
const snapshot = PageSnapshot.fromHTMLString(responseText);
|
|
2827
|
+
this.snapshotCache.put(location, snapshot);
|
|
2828
|
+
}
|
|
2829
|
+
catch (_) {
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2519
2834
|
class Session {
|
|
2520
2835
|
constructor() {
|
|
2521
2836
|
this.navigator = new Navigator(this);
|
|
2522
2837
|
this.history = new History(this);
|
|
2838
|
+
this.preloader = new Preloader(this);
|
|
2523
2839
|
this.view = new PageView(this, document.documentElement);
|
|
2524
2840
|
this.adapter = new BrowserAdapter(this);
|
|
2525
2841
|
this.pageObserver = new PageObserver(this);
|
|
2526
2842
|
this.cacheObserver = new CacheObserver();
|
|
2527
|
-
this.linkClickObserver = new LinkClickObserver(this);
|
|
2528
|
-
this.formSubmitObserver = new FormSubmitObserver(this);
|
|
2843
|
+
this.linkClickObserver = new LinkClickObserver(this, window);
|
|
2844
|
+
this.formSubmitObserver = new FormSubmitObserver(this, document);
|
|
2529
2845
|
this.scrollObserver = new ScrollObserver(this);
|
|
2530
2846
|
this.streamObserver = new StreamObserver(this);
|
|
2531
|
-
this.
|
|
2847
|
+
this.formLinkClickObserver = new FormLinkClickObserver(this, document.documentElement);
|
|
2848
|
+
this.frameRedirector = new FrameRedirector(this, document.documentElement);
|
|
2849
|
+
this.streamMessageRenderer = new StreamMessageRenderer();
|
|
2532
2850
|
this.drive = true;
|
|
2533
2851
|
this.enabled = true;
|
|
2534
2852
|
this.progressBarDelay = 500;
|
|
2535
2853
|
this.started = false;
|
|
2854
|
+
this.formMode = "on";
|
|
2536
2855
|
}
|
|
2537
2856
|
start() {
|
|
2538
2857
|
if (!this.started) {
|
|
2539
2858
|
this.pageObserver.start();
|
|
2540
2859
|
this.cacheObserver.start();
|
|
2860
|
+
this.formLinkClickObserver.start();
|
|
2541
2861
|
this.linkClickObserver.start();
|
|
2542
2862
|
this.formSubmitObserver.start();
|
|
2543
2863
|
this.scrollObserver.start();
|
|
2544
2864
|
this.streamObserver.start();
|
|
2545
2865
|
this.frameRedirector.start();
|
|
2546
2866
|
this.history.start();
|
|
2867
|
+
this.preloader.start();
|
|
2547
2868
|
this.started = true;
|
|
2548
2869
|
this.enabled = true;
|
|
2549
2870
|
}
|
|
@@ -2555,6 +2876,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2555
2876
|
if (this.started) {
|
|
2556
2877
|
this.pageObserver.stop();
|
|
2557
2878
|
this.cacheObserver.stop();
|
|
2879
|
+
this.formLinkClickObserver.stop();
|
|
2558
2880
|
this.linkClickObserver.stop();
|
|
2559
2881
|
this.formSubmitObserver.stop();
|
|
2560
2882
|
this.scrollObserver.stop();
|
|
@@ -2568,7 +2890,14 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2568
2890
|
this.adapter = adapter;
|
|
2569
2891
|
}
|
|
2570
2892
|
visit(location, options = {}) {
|
|
2571
|
-
|
|
2893
|
+
const frameElement = options.frame ? document.getElementById(options.frame) : null;
|
|
2894
|
+
if (frameElement instanceof FrameElement) {
|
|
2895
|
+
frameElement.src = location.toString();
|
|
2896
|
+
return frameElement.loaded;
|
|
2897
|
+
}
|
|
2898
|
+
else {
|
|
2899
|
+
return this.navigator.proposeVisit(expandURL(location), options);
|
|
2900
|
+
}
|
|
2572
2901
|
}
|
|
2573
2902
|
connectStreamSource(source) {
|
|
2574
2903
|
this.streamObserver.connectStreamSource(source);
|
|
@@ -2577,7 +2906,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2577
2906
|
this.streamObserver.disconnectStreamSource(source);
|
|
2578
2907
|
}
|
|
2579
2908
|
renderStreamMessage(message) {
|
|
2580
|
-
|
|
2909
|
+
this.streamMessageRenderer.render(StreamMessage.wrap(message));
|
|
2581
2910
|
}
|
|
2582
2911
|
clearCache() {
|
|
2583
2912
|
this.view.clearSnapshotCache();
|
|
@@ -2585,6 +2914,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2585
2914
|
setProgressBarDelay(delay) {
|
|
2586
2915
|
this.progressBarDelay = delay;
|
|
2587
2916
|
}
|
|
2917
|
+
setFormMode(mode) {
|
|
2918
|
+
this.formMode = mode;
|
|
2919
|
+
}
|
|
2588
2920
|
get location() {
|
|
2589
2921
|
return this.history.location;
|
|
2590
2922
|
}
|
|
@@ -2593,63 +2925,53 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2593
2925
|
}
|
|
2594
2926
|
historyPoppedToLocationWithRestorationIdentifier(location, restorationIdentifier) {
|
|
2595
2927
|
if (this.enabled) {
|
|
2596
|
-
this.navigator.startVisit(location, restorationIdentifier, {
|
|
2928
|
+
this.navigator.startVisit(location, restorationIdentifier, {
|
|
2929
|
+
action: "restore",
|
|
2930
|
+
historyChanged: true,
|
|
2931
|
+
});
|
|
2597
2932
|
}
|
|
2598
2933
|
else {
|
|
2599
|
-
this.adapter.pageInvalidated(
|
|
2934
|
+
this.adapter.pageInvalidated({
|
|
2935
|
+
reason: "turbo_disabled",
|
|
2936
|
+
});
|
|
2600
2937
|
}
|
|
2601
2938
|
}
|
|
2602
2939
|
scrollPositionChanged(position) {
|
|
2603
2940
|
this.history.updateRestorationData({ scrollPosition: position });
|
|
2604
2941
|
}
|
|
2605
|
-
|
|
2606
|
-
return this.
|
|
2607
|
-
|
|
2608
|
-
|
|
2942
|
+
willSubmitFormLinkToLocation(link, location) {
|
|
2943
|
+
return this.elementIsNavigatable(link) && locationIsVisitable(location, this.snapshot.rootLocation);
|
|
2944
|
+
}
|
|
2945
|
+
submittedFormLinkToLocation() { }
|
|
2946
|
+
willFollowLinkToLocation(link, location, event) {
|
|
2947
|
+
return (this.elementIsNavigatable(link) &&
|
|
2948
|
+
locationIsVisitable(location, this.snapshot.rootLocation) &&
|
|
2949
|
+
this.applicationAllowsFollowingLinkToLocation(link, location, event));
|
|
2609
2950
|
}
|
|
2610
2951
|
followedLinkToLocation(link, location) {
|
|
2611
2952
|
const action = this.getActionForLink(link);
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
convertLinkWithMethodClickToFormSubmission(link) {
|
|
2615
|
-
const linkMethod = link.getAttribute("data-turbo-method");
|
|
2616
|
-
if (linkMethod) {
|
|
2617
|
-
const form = document.createElement("form");
|
|
2618
|
-
form.method = linkMethod;
|
|
2619
|
-
form.action = link.getAttribute("href") || "undefined";
|
|
2620
|
-
form.hidden = true;
|
|
2621
|
-
if (link.hasAttribute("data-turbo-confirm")) {
|
|
2622
|
-
form.setAttribute("data-turbo-confirm", link.getAttribute("data-turbo-confirm"));
|
|
2623
|
-
}
|
|
2624
|
-
const frame = this.getTargetFrameForLink(link);
|
|
2625
|
-
if (frame) {
|
|
2626
|
-
form.setAttribute("data-turbo-frame", frame);
|
|
2627
|
-
form.addEventListener("turbo:submit-start", () => form.remove());
|
|
2628
|
-
}
|
|
2629
|
-
else {
|
|
2630
|
-
form.addEventListener("submit", () => form.remove());
|
|
2631
|
-
}
|
|
2632
|
-
document.body.appendChild(form);
|
|
2633
|
-
return dispatch("submit", { cancelable: true, target: form });
|
|
2634
|
-
}
|
|
2635
|
-
else {
|
|
2636
|
-
return false;
|
|
2637
|
-
}
|
|
2953
|
+
const acceptsStreamResponse = link.hasAttribute("data-turbo-stream");
|
|
2954
|
+
this.visit(location.href, { action, acceptsStreamResponse, initiator: link });
|
|
2638
2955
|
}
|
|
2639
|
-
|
|
2640
|
-
return this.locationWithActionIsSamePage(location, action) ||
|
|
2956
|
+
allowsVisitingLocation(location, options = {}) {
|
|
2957
|
+
return (this.locationWithActionIsSamePage(location, options.action) ||
|
|
2958
|
+
this.applicationAllowsVisitingLocation(location, options));
|
|
2641
2959
|
}
|
|
2642
2960
|
visitProposedToLocation(location, options) {
|
|
2643
2961
|
extendURLWithDeprecatedProperties(location);
|
|
2644
|
-
this.adapter.visitProposedToLocation(location, options);
|
|
2962
|
+
return this.adapter.visitProposedToLocation(location, options);
|
|
2645
2963
|
}
|
|
2646
2964
|
visitStarted(visit) {
|
|
2965
|
+
if (!visit.acceptsStreamResponse) {
|
|
2966
|
+
markAsBusy(document.documentElement);
|
|
2967
|
+
}
|
|
2647
2968
|
extendURLWithDeprecatedProperties(visit.location);
|
|
2648
2969
|
if (!visit.silent) {
|
|
2649
|
-
this.notifyApplicationAfterVisitingLocation(visit.location, visit.action);
|
|
2970
|
+
this.notifyApplicationAfterVisitingLocation(visit.location, visit.action, visit.initiator);
|
|
2650
2971
|
}
|
|
2651
2972
|
}
|
|
2652
2973
|
visitCompleted(visit) {
|
|
2974
|
+
clearBusyState(document.documentElement);
|
|
2653
2975
|
this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());
|
|
2654
2976
|
}
|
|
2655
2977
|
locationWithActionIsSamePage(location, action) {
|
|
@@ -2660,9 +2982,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2660
2982
|
}
|
|
2661
2983
|
willSubmitForm(form, submitter) {
|
|
2662
2984
|
const action = getAction(form, submitter);
|
|
2663
|
-
return this.
|
|
2664
|
-
|
|
2665
|
-
&& locationIsVisitable(expandURL(action), this.snapshot.rootLocation);
|
|
2985
|
+
return (this.submissionIsNavigatable(form, submitter) &&
|
|
2986
|
+
locationIsVisitable(expandURL(action), this.snapshot.rootLocation));
|
|
2666
2987
|
}
|
|
2667
2988
|
formSubmitted(form, submitter) {
|
|
2668
2989
|
this.navigator.submitForm(form, submitter);
|
|
@@ -2686,16 +3007,23 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2686
3007
|
this.notifyApplicationBeforeCachingSnapshot();
|
|
2687
3008
|
}
|
|
2688
3009
|
}
|
|
2689
|
-
allowsImmediateRender({ element },
|
|
2690
|
-
const event = this.notifyApplicationBeforeRender(element,
|
|
2691
|
-
|
|
3010
|
+
allowsImmediateRender({ element }, options) {
|
|
3011
|
+
const event = this.notifyApplicationBeforeRender(element, options);
|
|
3012
|
+
const { defaultPrevented, detail: { render }, } = event;
|
|
3013
|
+
if (this.view.renderer && render) {
|
|
3014
|
+
this.view.renderer.renderElement = render;
|
|
3015
|
+
}
|
|
3016
|
+
return !defaultPrevented;
|
|
2692
3017
|
}
|
|
2693
|
-
viewRenderedSnapshot(
|
|
3018
|
+
viewRenderedSnapshot(_snapshot, _isPreview) {
|
|
2694
3019
|
this.view.lastRenderedLocation = this.history.location;
|
|
2695
3020
|
this.notifyApplicationAfterRender();
|
|
2696
3021
|
}
|
|
2697
|
-
|
|
2698
|
-
this.
|
|
3022
|
+
preloadOnLoadLinksForView(element) {
|
|
3023
|
+
this.preloader.preloadOnLoadLinksForView(element);
|
|
3024
|
+
}
|
|
3025
|
+
viewInvalidated(reason) {
|
|
3026
|
+
this.adapter.pageInvalidated(reason);
|
|
2699
3027
|
}
|
|
2700
3028
|
frameLoaded(frame) {
|
|
2701
3029
|
this.notifyApplicationAfterFrameLoad(frame);
|
|
@@ -2703,49 +3031,85 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2703
3031
|
frameRendered(fetchResponse, frame) {
|
|
2704
3032
|
this.notifyApplicationAfterFrameRender(fetchResponse, frame);
|
|
2705
3033
|
}
|
|
2706
|
-
applicationAllowsFollowingLinkToLocation(link, location) {
|
|
2707
|
-
const event = this.notifyApplicationAfterClickingLinkToLocation(link, location);
|
|
3034
|
+
applicationAllowsFollowingLinkToLocation(link, location, ev) {
|
|
3035
|
+
const event = this.notifyApplicationAfterClickingLinkToLocation(link, location, ev);
|
|
2708
3036
|
return !event.defaultPrevented;
|
|
2709
3037
|
}
|
|
2710
|
-
applicationAllowsVisitingLocation(location) {
|
|
2711
|
-
const event = this.notifyApplicationBeforeVisitingLocation(location);
|
|
3038
|
+
applicationAllowsVisitingLocation(location, options = {}) {
|
|
3039
|
+
const event = this.notifyApplicationBeforeVisitingLocation(location, options.initiator);
|
|
2712
3040
|
return !event.defaultPrevented;
|
|
2713
3041
|
}
|
|
2714
|
-
notifyApplicationAfterClickingLinkToLocation(link, location) {
|
|
2715
|
-
return dispatch("turbo:click", {
|
|
3042
|
+
notifyApplicationAfterClickingLinkToLocation(link, location, event) {
|
|
3043
|
+
return dispatch("turbo:click", {
|
|
3044
|
+
target: link,
|
|
3045
|
+
detail: { url: location.href, originalEvent: event },
|
|
3046
|
+
cancelable: true,
|
|
3047
|
+
});
|
|
2716
3048
|
}
|
|
2717
|
-
notifyApplicationBeforeVisitingLocation(location) {
|
|
2718
|
-
return dispatch("turbo:before-visit", {
|
|
3049
|
+
notifyApplicationBeforeVisitingLocation(location, element) {
|
|
3050
|
+
return dispatch("turbo:before-visit", {
|
|
3051
|
+
target: element,
|
|
3052
|
+
detail: { url: location.href },
|
|
3053
|
+
cancelable: true,
|
|
3054
|
+
});
|
|
2719
3055
|
}
|
|
2720
|
-
notifyApplicationAfterVisitingLocation(location, action) {
|
|
2721
|
-
|
|
2722
|
-
|
|
3056
|
+
notifyApplicationAfterVisitingLocation(location, action, element) {
|
|
3057
|
+
return dispatch("turbo:visit", {
|
|
3058
|
+
target: element,
|
|
3059
|
+
detail: { url: location.href, action },
|
|
3060
|
+
});
|
|
2723
3061
|
}
|
|
2724
3062
|
notifyApplicationBeforeCachingSnapshot() {
|
|
2725
3063
|
return dispatch("turbo:before-cache");
|
|
2726
3064
|
}
|
|
2727
|
-
notifyApplicationBeforeRender(newBody,
|
|
2728
|
-
return dispatch("turbo:before-render", {
|
|
3065
|
+
notifyApplicationBeforeRender(newBody, options) {
|
|
3066
|
+
return dispatch("turbo:before-render", {
|
|
3067
|
+
detail: Object.assign({ newBody }, options),
|
|
3068
|
+
cancelable: true,
|
|
3069
|
+
});
|
|
2729
3070
|
}
|
|
2730
3071
|
notifyApplicationAfterRender() {
|
|
2731
3072
|
return dispatch("turbo:render");
|
|
2732
3073
|
}
|
|
2733
3074
|
notifyApplicationAfterPageLoad(timing = {}) {
|
|
2734
|
-
|
|
2735
|
-
|
|
3075
|
+
return dispatch("turbo:load", {
|
|
3076
|
+
detail: { url: this.location.href, timing },
|
|
3077
|
+
});
|
|
2736
3078
|
}
|
|
2737
3079
|
notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL) {
|
|
2738
|
-
dispatchEvent(new HashChangeEvent("hashchange", {
|
|
3080
|
+
dispatchEvent(new HashChangeEvent("hashchange", {
|
|
3081
|
+
oldURL: oldURL.toString(),
|
|
3082
|
+
newURL: newURL.toString(),
|
|
3083
|
+
}));
|
|
2739
3084
|
}
|
|
2740
3085
|
notifyApplicationAfterFrameLoad(frame) {
|
|
2741
3086
|
return dispatch("turbo:frame-load", { target: frame });
|
|
2742
3087
|
}
|
|
2743
3088
|
notifyApplicationAfterFrameRender(fetchResponse, frame) {
|
|
2744
|
-
return dispatch("turbo:frame-render", {
|
|
3089
|
+
return dispatch("turbo:frame-render", {
|
|
3090
|
+
detail: { fetchResponse },
|
|
3091
|
+
target: frame,
|
|
3092
|
+
cancelable: true,
|
|
3093
|
+
});
|
|
2745
3094
|
}
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
3095
|
+
submissionIsNavigatable(form, submitter) {
|
|
3096
|
+
if (this.formMode == "off") {
|
|
3097
|
+
return false;
|
|
3098
|
+
}
|
|
3099
|
+
else {
|
|
3100
|
+
const submitterIsNavigatable = submitter ? this.elementIsNavigatable(submitter) : true;
|
|
3101
|
+
if (this.formMode == "optin") {
|
|
3102
|
+
return submitterIsNavigatable && form.closest('[data-turbo="true"]') != null;
|
|
3103
|
+
}
|
|
3104
|
+
else {
|
|
3105
|
+
return submitterIsNavigatable && this.elementIsNavigatable(form);
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
elementIsNavigatable(element) {
|
|
3110
|
+
const container = element.closest("[data-turbo]");
|
|
3111
|
+
const withinFrame = element.closest("turbo-frame");
|
|
3112
|
+
if (this.drive || withinFrame) {
|
|
2749
3113
|
if (container) {
|
|
2750
3114
|
return container.getAttribute("data-turbo") != "false";
|
|
2751
3115
|
}
|
|
@@ -2766,18 +3130,6 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2766
3130
|
const action = link.getAttribute("data-turbo-action");
|
|
2767
3131
|
return isAction(action) ? action : "advance";
|
|
2768
3132
|
}
|
|
2769
|
-
getTargetFrameForLink(link) {
|
|
2770
|
-
const frame = link.getAttribute("data-turbo-frame");
|
|
2771
|
-
if (frame) {
|
|
2772
|
-
return frame;
|
|
2773
|
-
}
|
|
2774
|
-
else {
|
|
2775
|
-
const container = link.closest("turbo-frame");
|
|
2776
|
-
if (container) {
|
|
2777
|
-
return container.id;
|
|
2778
|
-
}
|
|
2779
|
-
}
|
|
2780
|
-
}
|
|
2781
3133
|
get snapshot() {
|
|
2782
3134
|
return this.view.snapshot;
|
|
2783
3135
|
}
|
|
@@ -2789,11 +3141,59 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2789
3141
|
absoluteURL: {
|
|
2790
3142
|
get() {
|
|
2791
3143
|
return this.toString();
|
|
2792
|
-
}
|
|
3144
|
+
},
|
|
3145
|
+
},
|
|
3146
|
+
};
|
|
3147
|
+
|
|
3148
|
+
class Cache {
|
|
3149
|
+
constructor(session) {
|
|
3150
|
+
this.session = session;
|
|
3151
|
+
}
|
|
3152
|
+
clear() {
|
|
3153
|
+
this.session.clearCache();
|
|
3154
|
+
}
|
|
3155
|
+
resetCacheControl() {
|
|
3156
|
+
this.setCacheControl("");
|
|
2793
3157
|
}
|
|
3158
|
+
exemptPageFromCache() {
|
|
3159
|
+
this.setCacheControl("no-cache");
|
|
3160
|
+
}
|
|
3161
|
+
exemptPageFromPreview() {
|
|
3162
|
+
this.setCacheControl("no-preview");
|
|
3163
|
+
}
|
|
3164
|
+
setCacheControl(value) {
|
|
3165
|
+
setMetaContent("turbo-cache-control", value);
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
|
|
3169
|
+
const StreamActions = {
|
|
3170
|
+
after() {
|
|
3171
|
+
this.targetElements.forEach((e) => { var _a; return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e.nextSibling); });
|
|
3172
|
+
},
|
|
3173
|
+
append() {
|
|
3174
|
+
this.removeDuplicateTargetChildren();
|
|
3175
|
+
this.targetElements.forEach((e) => e.append(this.templateContent));
|
|
3176
|
+
},
|
|
3177
|
+
before() {
|
|
3178
|
+
this.targetElements.forEach((e) => { var _a; return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e); });
|
|
3179
|
+
},
|
|
3180
|
+
prepend() {
|
|
3181
|
+
this.removeDuplicateTargetChildren();
|
|
3182
|
+
this.targetElements.forEach((e) => e.prepend(this.templateContent));
|
|
3183
|
+
},
|
|
3184
|
+
remove() {
|
|
3185
|
+
this.targetElements.forEach((e) => e.remove());
|
|
3186
|
+
},
|
|
3187
|
+
replace() {
|
|
3188
|
+
this.targetElements.forEach((e) => e.replaceWith(this.templateContent));
|
|
3189
|
+
},
|
|
3190
|
+
update() {
|
|
3191
|
+
this.targetElements.forEach((e) => e.replaceChildren(this.templateContent));
|
|
3192
|
+
},
|
|
2794
3193
|
};
|
|
2795
3194
|
|
|
2796
|
-
const session = new Session;
|
|
3195
|
+
const session = new Session();
|
|
3196
|
+
const cache = new Cache(session);
|
|
2797
3197
|
const { navigator: navigator$1 } = session;
|
|
2798
3198
|
function start() {
|
|
2799
3199
|
session.start();
|
|
@@ -2802,7 +3202,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2802
3202
|
session.registerAdapter(adapter);
|
|
2803
3203
|
}
|
|
2804
3204
|
function visit(location, options) {
|
|
2805
|
-
session.visit(location, options);
|
|
3205
|
+
return session.visit(location, options);
|
|
2806
3206
|
}
|
|
2807
3207
|
function connectStreamSource(source) {
|
|
2808
3208
|
session.connectStreamSource(source);
|
|
@@ -2814,6 +3214,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2814
3214
|
session.renderStreamMessage(message);
|
|
2815
3215
|
}
|
|
2816
3216
|
function clearCache() {
|
|
3217
|
+
console.warn("Please replace `Turbo.clearCache()` with `Turbo.cache.clear()`. The top-level function is deprecated and will be removed in a future version of Turbo.`");
|
|
2817
3218
|
session.clearCache();
|
|
2818
3219
|
}
|
|
2819
3220
|
function setProgressBarDelay(delay) {
|
|
@@ -2822,13 +3223,18 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2822
3223
|
function setConfirmMethod(confirmMethod) {
|
|
2823
3224
|
FormSubmission.confirmMethod = confirmMethod;
|
|
2824
3225
|
}
|
|
3226
|
+
function setFormMode(mode) {
|
|
3227
|
+
session.setFormMode(mode);
|
|
3228
|
+
}
|
|
2825
3229
|
|
|
2826
3230
|
var Turbo = /*#__PURE__*/Object.freeze({
|
|
2827
3231
|
__proto__: null,
|
|
2828
3232
|
navigator: navigator$1,
|
|
2829
3233
|
session: session,
|
|
3234
|
+
cache: cache,
|
|
2830
3235
|
PageRenderer: PageRenderer,
|
|
2831
3236
|
PageSnapshot: PageSnapshot,
|
|
3237
|
+
FrameRenderer: FrameRenderer,
|
|
2832
3238
|
start: start,
|
|
2833
3239
|
registerAdapter: registerAdapter,
|
|
2834
3240
|
visit: visit,
|
|
@@ -2837,55 +3243,80 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2837
3243
|
renderStreamMessage: renderStreamMessage,
|
|
2838
3244
|
clearCache: clearCache,
|
|
2839
3245
|
setProgressBarDelay: setProgressBarDelay,
|
|
2840
|
-
setConfirmMethod: setConfirmMethod
|
|
3246
|
+
setConfirmMethod: setConfirmMethod,
|
|
3247
|
+
setFormMode: setFormMode,
|
|
3248
|
+
StreamActions: StreamActions
|
|
2841
3249
|
});
|
|
2842
3250
|
|
|
2843
3251
|
class FrameController {
|
|
2844
3252
|
constructor(element) {
|
|
2845
|
-
this.fetchResponseLoaded = (
|
|
3253
|
+
this.fetchResponseLoaded = (_fetchResponse) => { };
|
|
2846
3254
|
this.currentFetchRequest = null;
|
|
2847
3255
|
this.resolveVisitPromise = () => { };
|
|
2848
3256
|
this.connected = false;
|
|
2849
3257
|
this.hasBeenLoaded = false;
|
|
2850
|
-
this.
|
|
3258
|
+
this.ignoredAttributes = new Set();
|
|
3259
|
+
this.action = null;
|
|
3260
|
+
this.visitCachedSnapshot = ({ element }) => {
|
|
3261
|
+
const frame = element.querySelector("#" + this.element.id);
|
|
3262
|
+
if (frame && this.previousFrameElement) {
|
|
3263
|
+
frame.replaceChildren(...this.previousFrameElement.children);
|
|
3264
|
+
}
|
|
3265
|
+
delete this.previousFrameElement;
|
|
3266
|
+
};
|
|
2851
3267
|
this.element = element;
|
|
2852
3268
|
this.view = new FrameView(this, this.element);
|
|
2853
3269
|
this.appearanceObserver = new AppearanceObserver(this, this.element);
|
|
2854
|
-
this.
|
|
2855
|
-
this.
|
|
3270
|
+
this.formLinkClickObserver = new FormLinkClickObserver(this, this.element);
|
|
3271
|
+
this.linkClickObserver = new LinkClickObserver(this, this.element);
|
|
3272
|
+
this.restorationIdentifier = uuid();
|
|
3273
|
+
this.formSubmitObserver = new FormSubmitObserver(this, this.element);
|
|
2856
3274
|
}
|
|
2857
3275
|
connect() {
|
|
2858
3276
|
if (!this.connected) {
|
|
2859
3277
|
this.connected = true;
|
|
2860
|
-
this.
|
|
2861
|
-
if (this.loadingStyle == FrameLoadingStyle.lazy) {
|
|
3278
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.lazy) {
|
|
2862
3279
|
this.appearanceObserver.start();
|
|
2863
3280
|
}
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
3281
|
+
else {
|
|
3282
|
+
this.loadSourceURL();
|
|
3283
|
+
}
|
|
3284
|
+
this.formLinkClickObserver.start();
|
|
3285
|
+
this.linkClickObserver.start();
|
|
3286
|
+
this.formSubmitObserver.start();
|
|
2867
3287
|
}
|
|
2868
3288
|
}
|
|
2869
3289
|
disconnect() {
|
|
2870
3290
|
if (this.connected) {
|
|
2871
3291
|
this.connected = false;
|
|
2872
3292
|
this.appearanceObserver.stop();
|
|
2873
|
-
this.
|
|
2874
|
-
this.
|
|
3293
|
+
this.formLinkClickObserver.stop();
|
|
3294
|
+
this.linkClickObserver.stop();
|
|
3295
|
+
this.formSubmitObserver.stop();
|
|
2875
3296
|
}
|
|
2876
3297
|
}
|
|
2877
3298
|
disabledChanged() {
|
|
2878
|
-
if (this.loadingStyle == FrameLoadingStyle.eager) {
|
|
3299
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.eager) {
|
|
2879
3300
|
this.loadSourceURL();
|
|
2880
3301
|
}
|
|
2881
3302
|
}
|
|
2882
3303
|
sourceURLChanged() {
|
|
2883
|
-
if (this.
|
|
3304
|
+
if (this.isIgnoringChangesTo("src"))
|
|
3305
|
+
return;
|
|
3306
|
+
if (this.element.isConnected) {
|
|
3307
|
+
this.complete = false;
|
|
3308
|
+
}
|
|
3309
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.eager || this.hasBeenLoaded) {
|
|
2884
3310
|
this.loadSourceURL();
|
|
2885
3311
|
}
|
|
2886
3312
|
}
|
|
3313
|
+
completeChanged() {
|
|
3314
|
+
if (this.isIgnoringChangesTo("complete"))
|
|
3315
|
+
return;
|
|
3316
|
+
this.loadSourceURL();
|
|
3317
|
+
}
|
|
2887
3318
|
loadingStyleChanged() {
|
|
2888
|
-
if (this.loadingStyle == FrameLoadingStyle.lazy) {
|
|
3319
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.lazy) {
|
|
2889
3320
|
this.appearanceObserver.start();
|
|
2890
3321
|
}
|
|
2891
3322
|
else {
|
|
@@ -2894,21 +3325,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2894
3325
|
}
|
|
2895
3326
|
}
|
|
2896
3327
|
async loadSourceURL() {
|
|
2897
|
-
if (
|
|
2898
|
-
|
|
2899
|
-
this.
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
this.element.loaded = this.visit(expandURL(this.sourceURL));
|
|
2903
|
-
this.appearanceObserver.stop();
|
|
2904
|
-
await this.element.loaded;
|
|
2905
|
-
this.hasBeenLoaded = true;
|
|
2906
|
-
}
|
|
2907
|
-
catch (error) {
|
|
2908
|
-
this.currentURL = previousURL;
|
|
2909
|
-
throw error;
|
|
2910
|
-
}
|
|
2911
|
-
}
|
|
3328
|
+
if (this.enabled && this.isActive && !this.complete && this.sourceURL) {
|
|
3329
|
+
this.element.loaded = this.visit(expandURL(this.sourceURL));
|
|
3330
|
+
this.appearanceObserver.stop();
|
|
3331
|
+
await this.element.loaded;
|
|
3332
|
+
this.hasBeenLoaded = true;
|
|
2912
3333
|
}
|
|
2913
3334
|
}
|
|
2914
3335
|
async loadResponse(fetchResponse) {
|
|
@@ -2919,14 +3340,23 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2919
3340
|
const html = await fetchResponse.responseHTML;
|
|
2920
3341
|
if (html) {
|
|
2921
3342
|
const { body } = parseHTMLDocument(html);
|
|
2922
|
-
const
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
3343
|
+
const newFrameElement = await this.extractForeignFrameElement(body);
|
|
3344
|
+
if (newFrameElement) {
|
|
3345
|
+
const snapshot = new Snapshot(newFrameElement);
|
|
3346
|
+
const renderer = new FrameRenderer(this, this.view.snapshot, snapshot, FrameRenderer.renderElement, false, false);
|
|
3347
|
+
if (this.view.renderPromise)
|
|
3348
|
+
await this.view.renderPromise;
|
|
3349
|
+
this.changeHistory();
|
|
3350
|
+
await this.view.render(renderer);
|
|
3351
|
+
this.complete = true;
|
|
3352
|
+
session.frameRendered(fetchResponse, this.element);
|
|
3353
|
+
session.frameLoaded(this.element);
|
|
3354
|
+
this.fetchResponseLoaded(fetchResponse);
|
|
3355
|
+
}
|
|
3356
|
+
else if (this.willHandleFrameMissingFromResponse(fetchResponse)) {
|
|
3357
|
+
console.warn(`A matching frame for #${this.element.id} was missing from the response, transforming into full-page Visit.`);
|
|
3358
|
+
this.visitResponse(fetchResponse.response);
|
|
3359
|
+
}
|
|
2930
3360
|
}
|
|
2931
3361
|
}
|
|
2932
3362
|
catch (error) {
|
|
@@ -2937,56 +3367,66 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2937
3367
|
this.fetchResponseLoaded = () => { };
|
|
2938
3368
|
}
|
|
2939
3369
|
}
|
|
2940
|
-
elementAppearedInViewport(
|
|
3370
|
+
elementAppearedInViewport(_element) {
|
|
2941
3371
|
this.loadSourceURL();
|
|
2942
3372
|
}
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
3373
|
+
willSubmitFormLinkToLocation(link) {
|
|
3374
|
+
return link.closest("turbo-frame") == this.element && this.shouldInterceptNavigation(link);
|
|
3375
|
+
}
|
|
3376
|
+
submittedFormLinkToLocation(link, _location, form) {
|
|
3377
|
+
const frame = this.findFrameElement(link);
|
|
3378
|
+
if (frame)
|
|
3379
|
+
form.setAttribute("data-turbo-frame", frame.id);
|
|
2950
3380
|
}
|
|
2951
|
-
|
|
2952
|
-
this.
|
|
2953
|
-
this.navigateFrame(element, url);
|
|
3381
|
+
willFollowLinkToLocation(element) {
|
|
3382
|
+
return this.shouldInterceptNavigation(element);
|
|
2954
3383
|
}
|
|
2955
|
-
|
|
2956
|
-
|
|
3384
|
+
followedLinkToLocation(element, location) {
|
|
3385
|
+
this.navigateFrame(element, location.href);
|
|
2957
3386
|
}
|
|
2958
|
-
|
|
3387
|
+
willSubmitForm(element, submitter) {
|
|
3388
|
+
return element.closest("turbo-frame") == this.element && this.shouldInterceptNavigation(element, submitter);
|
|
3389
|
+
}
|
|
3390
|
+
formSubmitted(element, submitter) {
|
|
2959
3391
|
if (this.formSubmission) {
|
|
2960
3392
|
this.formSubmission.stop();
|
|
2961
3393
|
}
|
|
2962
|
-
this.reloadable = false;
|
|
2963
3394
|
this.formSubmission = new FormSubmission(this, element, submitter);
|
|
2964
3395
|
const { fetchRequest } = this.formSubmission;
|
|
2965
3396
|
this.prepareHeadersForRequest(fetchRequest.headers, fetchRequest);
|
|
2966
3397
|
this.formSubmission.start();
|
|
2967
3398
|
}
|
|
2968
3399
|
prepareHeadersForRequest(headers, request) {
|
|
3400
|
+
var _a;
|
|
2969
3401
|
headers["Turbo-Frame"] = this.id;
|
|
3402
|
+
if ((_a = this.currentNavigationElement) === null || _a === void 0 ? void 0 : _a.hasAttribute("data-turbo-stream")) {
|
|
3403
|
+
request.acceptResponseType(StreamMessage.contentType);
|
|
3404
|
+
}
|
|
2970
3405
|
}
|
|
2971
|
-
requestStarted(
|
|
3406
|
+
requestStarted(_request) {
|
|
2972
3407
|
markAsBusy(this.element);
|
|
2973
3408
|
}
|
|
2974
|
-
requestPreventedHandlingResponse(
|
|
3409
|
+
requestPreventedHandlingResponse(_request, _response) {
|
|
2975
3410
|
this.resolveVisitPromise();
|
|
2976
3411
|
}
|
|
2977
3412
|
async requestSucceededWithResponse(request, response) {
|
|
2978
3413
|
await this.loadResponse(response);
|
|
2979
3414
|
this.resolveVisitPromise();
|
|
2980
3415
|
}
|
|
2981
|
-
requestFailedWithResponse(request, response) {
|
|
3416
|
+
async requestFailedWithResponse(request, response) {
|
|
2982
3417
|
console.error(response);
|
|
3418
|
+
await this.loadResponse(response);
|
|
2983
3419
|
this.resolveVisitPromise();
|
|
2984
3420
|
}
|
|
2985
3421
|
requestErrored(request, error) {
|
|
2986
3422
|
console.error(error);
|
|
3423
|
+
dispatch("turbo:fetch-request-error", {
|
|
3424
|
+
target: this.element,
|
|
3425
|
+
detail: { request, error },
|
|
3426
|
+
});
|
|
2987
3427
|
this.resolveVisitPromise();
|
|
2988
3428
|
}
|
|
2989
|
-
requestFinished(
|
|
3429
|
+
requestFinished(_request) {
|
|
2990
3430
|
clearBusyState(this.element);
|
|
2991
3431
|
}
|
|
2992
3432
|
formSubmissionStarted({ formElement }) {
|
|
@@ -3006,19 +3446,32 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3006
3446
|
formSubmissionFinished({ formElement }) {
|
|
3007
3447
|
clearBusyState(formElement, this.findFrameElement(formElement));
|
|
3008
3448
|
}
|
|
3009
|
-
allowsImmediateRender(
|
|
3010
|
-
|
|
3449
|
+
allowsImmediateRender({ element: newFrame }, options) {
|
|
3450
|
+
const event = dispatch("turbo:before-frame-render", {
|
|
3451
|
+
target: this.element,
|
|
3452
|
+
detail: Object.assign({ newFrame }, options),
|
|
3453
|
+
cancelable: true,
|
|
3454
|
+
});
|
|
3455
|
+
const { defaultPrevented, detail: { render }, } = event;
|
|
3456
|
+
if (this.view.renderer && render) {
|
|
3457
|
+
this.view.renderer.renderElement = render;
|
|
3458
|
+
}
|
|
3459
|
+
return !defaultPrevented;
|
|
3011
3460
|
}
|
|
3012
|
-
viewRenderedSnapshot(
|
|
3461
|
+
viewRenderedSnapshot(_snapshot, _isPreview) { }
|
|
3462
|
+
preloadOnLoadLinksForView(element) {
|
|
3463
|
+
session.preloadOnLoadLinksForView(element);
|
|
3013
3464
|
}
|
|
3014
|
-
viewInvalidated() {
|
|
3465
|
+
viewInvalidated() { }
|
|
3466
|
+
willRenderFrame(currentElement, _newElement) {
|
|
3467
|
+
this.previousFrameElement = currentElement.cloneNode(true);
|
|
3015
3468
|
}
|
|
3016
3469
|
async visit(url) {
|
|
3017
3470
|
var _a;
|
|
3018
|
-
const request = new FetchRequest(this, FetchMethod.get, url, new URLSearchParams, this.element);
|
|
3471
|
+
const request = new FetchRequest(this, FetchMethod.get, url, new URLSearchParams(), this.element);
|
|
3019
3472
|
(_a = this.currentFetchRequest) === null || _a === void 0 ? void 0 : _a.cancel();
|
|
3020
3473
|
this.currentFetchRequest = request;
|
|
3021
|
-
return new Promise(resolve => {
|
|
3474
|
+
return new Promise((resolve) => {
|
|
3022
3475
|
this.resolveVisitPromise = () => {
|
|
3023
3476
|
this.resolveVisitPromise = () => { };
|
|
3024
3477
|
this.currentFetchRequest = null;
|
|
@@ -3030,23 +3483,64 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3030
3483
|
navigateFrame(element, url, submitter) {
|
|
3031
3484
|
const frame = this.findFrameElement(element, submitter);
|
|
3032
3485
|
this.proposeVisitIfNavigatedWithAction(frame, element, submitter);
|
|
3033
|
-
|
|
3034
|
-
|
|
3486
|
+
this.withCurrentNavigationElement(element, () => {
|
|
3487
|
+
frame.src = url;
|
|
3488
|
+
});
|
|
3035
3489
|
}
|
|
3036
3490
|
proposeVisitIfNavigatedWithAction(frame, element, submitter) {
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3491
|
+
this.action = getVisitAction(submitter, element, frame);
|
|
3492
|
+
this.frame = frame;
|
|
3493
|
+
if (isAction(this.action)) {
|
|
3494
|
+
const { visitCachedSnapshot } = frame.delegate;
|
|
3040
3495
|
frame.delegate.fetchResponseLoaded = (fetchResponse) => {
|
|
3041
3496
|
if (frame.src) {
|
|
3042
3497
|
const { statusCode, redirected } = fetchResponse;
|
|
3043
3498
|
const responseHTML = frame.ownerDocument.documentElement.outerHTML;
|
|
3044
3499
|
const response = { statusCode, redirected, responseHTML };
|
|
3045
|
-
|
|
3500
|
+
const options = {
|
|
3501
|
+
response,
|
|
3502
|
+
visitCachedSnapshot,
|
|
3503
|
+
willRender: false,
|
|
3504
|
+
updateHistory: false,
|
|
3505
|
+
restorationIdentifier: this.restorationIdentifier,
|
|
3506
|
+
};
|
|
3507
|
+
if (this.action)
|
|
3508
|
+
options.action = this.action;
|
|
3509
|
+
session.visit(frame.src, options);
|
|
3046
3510
|
}
|
|
3047
3511
|
};
|
|
3048
3512
|
}
|
|
3049
3513
|
}
|
|
3514
|
+
changeHistory() {
|
|
3515
|
+
if (this.action && this.frame) {
|
|
3516
|
+
const method = getHistoryMethodForAction(this.action);
|
|
3517
|
+
session.history.update(method, expandURL(this.frame.src || ""), this.restorationIdentifier);
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3520
|
+
willHandleFrameMissingFromResponse(fetchResponse) {
|
|
3521
|
+
this.element.setAttribute("complete", "");
|
|
3522
|
+
const response = fetchResponse.response;
|
|
3523
|
+
const visit = async (url, options = {}) => {
|
|
3524
|
+
if (url instanceof Response) {
|
|
3525
|
+
this.visitResponse(url);
|
|
3526
|
+
}
|
|
3527
|
+
else {
|
|
3528
|
+
session.visit(url, options);
|
|
3529
|
+
}
|
|
3530
|
+
};
|
|
3531
|
+
const event = dispatch("turbo:frame-missing", {
|
|
3532
|
+
target: this.element,
|
|
3533
|
+
detail: { response, visit },
|
|
3534
|
+
cancelable: true,
|
|
3535
|
+
});
|
|
3536
|
+
return !event.defaultPrevented;
|
|
3537
|
+
}
|
|
3538
|
+
async visitResponse(response) {
|
|
3539
|
+
const wrapped = new FetchResponse(response);
|
|
3540
|
+
const responseHTML = await wrapped.responseHTML;
|
|
3541
|
+
const { location, redirected, statusCode } = wrapped;
|
|
3542
|
+
return session.visit(location, { response: { redirected, statusCode, responseHTML } });
|
|
3543
|
+
}
|
|
3050
3544
|
findFrameElement(element, submitter) {
|
|
3051
3545
|
var _a;
|
|
3052
3546
|
const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target");
|
|
@@ -3056,19 +3550,21 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3056
3550
|
let element;
|
|
3057
3551
|
const id = CSS.escape(this.id);
|
|
3058
3552
|
try {
|
|
3059
|
-
|
|
3553
|
+
element = activateElement(container.querySelector(`turbo-frame#${id}`), this.sourceURL);
|
|
3554
|
+
if (element) {
|
|
3060
3555
|
return element;
|
|
3061
3556
|
}
|
|
3062
|
-
|
|
3557
|
+
element = activateElement(container.querySelector(`turbo-frame[src][recurse~=${id}]`), this.sourceURL);
|
|
3558
|
+
if (element) {
|
|
3063
3559
|
await element.loaded;
|
|
3064
3560
|
return await this.extractForeignFrameElement(element);
|
|
3065
3561
|
}
|
|
3066
|
-
console.error(`Response has no matching <turbo-frame id="${id}"> element`);
|
|
3067
3562
|
}
|
|
3068
3563
|
catch (error) {
|
|
3069
3564
|
console.error(error);
|
|
3565
|
+
return new FrameElement();
|
|
3070
3566
|
}
|
|
3071
|
-
return
|
|
3567
|
+
return null;
|
|
3072
3568
|
}
|
|
3073
3569
|
formActionIsVisitable(form, submitter) {
|
|
3074
3570
|
const action = getAction(form, submitter);
|
|
@@ -3088,10 +3584,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3088
3584
|
return !frameElement.disabled;
|
|
3089
3585
|
}
|
|
3090
3586
|
}
|
|
3091
|
-
if (!session.
|
|
3587
|
+
if (!session.elementIsNavigatable(element)) {
|
|
3092
3588
|
return false;
|
|
3093
3589
|
}
|
|
3094
|
-
if (submitter && !session.
|
|
3590
|
+
if (submitter && !session.elementIsNavigatable(submitter)) {
|
|
3095
3591
|
return false;
|
|
3096
3592
|
}
|
|
3097
3593
|
return true;
|
|
@@ -3107,24 +3603,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3107
3603
|
return this.element.src;
|
|
3108
3604
|
}
|
|
3109
3605
|
}
|
|
3110
|
-
get reloadable() {
|
|
3111
|
-
const frame = this.findFrameElement(this.element);
|
|
3112
|
-
return frame.hasAttribute("reloadable");
|
|
3113
|
-
}
|
|
3114
|
-
set reloadable(value) {
|
|
3115
|
-
const frame = this.findFrameElement(this.element);
|
|
3116
|
-
if (value) {
|
|
3117
|
-
frame.setAttribute("reloadable", "");
|
|
3118
|
-
}
|
|
3119
|
-
else {
|
|
3120
|
-
frame.removeAttribute("reloadable");
|
|
3121
|
-
}
|
|
3122
|
-
}
|
|
3123
3606
|
set sourceURL(sourceURL) {
|
|
3124
|
-
this.
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
this.settingSourceURL = false;
|
|
3607
|
+
this.ignoringChangesToAttribute("src", () => {
|
|
3608
|
+
this.element.src = sourceURL !== null && sourceURL !== void 0 ? sourceURL : null;
|
|
3609
|
+
});
|
|
3128
3610
|
}
|
|
3129
3611
|
get loadingStyle() {
|
|
3130
3612
|
return this.element.loading;
|
|
@@ -3132,6 +3614,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3132
3614
|
get isLoading() {
|
|
3133
3615
|
return this.formSubmission !== undefined || this.resolveVisitPromise() !== undefined;
|
|
3134
3616
|
}
|
|
3617
|
+
get complete() {
|
|
3618
|
+
return this.element.hasAttribute("complete");
|
|
3619
|
+
}
|
|
3620
|
+
set complete(value) {
|
|
3621
|
+
this.ignoringChangesToAttribute("complete", () => {
|
|
3622
|
+
if (value) {
|
|
3623
|
+
this.element.setAttribute("complete", "");
|
|
3624
|
+
}
|
|
3625
|
+
else {
|
|
3626
|
+
this.element.removeAttribute("complete");
|
|
3627
|
+
}
|
|
3628
|
+
});
|
|
3629
|
+
}
|
|
3135
3630
|
get isActive() {
|
|
3136
3631
|
return this.element.isActive && this.connected;
|
|
3137
3632
|
}
|
|
@@ -3141,16 +3636,18 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3141
3636
|
const root = (_a = meta === null || meta === void 0 ? void 0 : meta.content) !== null && _a !== void 0 ? _a : "/";
|
|
3142
3637
|
return expandURL(root);
|
|
3143
3638
|
}
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
this.
|
|
3639
|
+
isIgnoringChangesTo(attributeName) {
|
|
3640
|
+
return this.ignoredAttributes.has(attributeName);
|
|
3641
|
+
}
|
|
3642
|
+
ignoringChangesToAttribute(attributeName, callback) {
|
|
3643
|
+
this.ignoredAttributes.add(attributeName);
|
|
3644
|
+
callback();
|
|
3645
|
+
this.ignoredAttributes.delete(attributeName);
|
|
3646
|
+
}
|
|
3647
|
+
withCurrentNavigationElement(element, callback) {
|
|
3648
|
+
this.currentNavigationElement = element;
|
|
3649
|
+
callback();
|
|
3650
|
+
delete this.currentNavigationElement;
|
|
3154
3651
|
}
|
|
3155
3652
|
}
|
|
3156
3653
|
function getFrameElementById(id) {
|
|
@@ -3178,36 +3675,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3178
3675
|
}
|
|
3179
3676
|
}
|
|
3180
3677
|
|
|
3181
|
-
const StreamActions = {
|
|
3182
|
-
after() {
|
|
3183
|
-
this.targetElements.forEach(e => { var _a; return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e.nextSibling); });
|
|
3184
|
-
},
|
|
3185
|
-
append() {
|
|
3186
|
-
this.removeDuplicateTargetChildren();
|
|
3187
|
-
this.targetElements.forEach(e => e.append(this.templateContent));
|
|
3188
|
-
},
|
|
3189
|
-
before() {
|
|
3190
|
-
this.targetElements.forEach(e => { var _a; return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e); });
|
|
3191
|
-
},
|
|
3192
|
-
prepend() {
|
|
3193
|
-
this.removeDuplicateTargetChildren();
|
|
3194
|
-
this.targetElements.forEach(e => e.prepend(this.templateContent));
|
|
3195
|
-
},
|
|
3196
|
-
remove() {
|
|
3197
|
-
this.targetElements.forEach(e => e.remove());
|
|
3198
|
-
},
|
|
3199
|
-
replace() {
|
|
3200
|
-
this.targetElements.forEach(e => e.replaceWith(this.templateContent));
|
|
3201
|
-
},
|
|
3202
|
-
update() {
|
|
3203
|
-
this.targetElements.forEach(e => {
|
|
3204
|
-
e.innerHTML = "";
|
|
3205
|
-
e.append(this.templateContent);
|
|
3206
|
-
});
|
|
3207
|
-
}
|
|
3208
|
-
};
|
|
3209
|
-
|
|
3210
3678
|
class StreamElement extends HTMLElement {
|
|
3679
|
+
static async renderElement(newElement) {
|
|
3680
|
+
await newElement.performAction();
|
|
3681
|
+
}
|
|
3211
3682
|
async connectedCallback() {
|
|
3212
3683
|
try {
|
|
3213
3684
|
await this.render();
|
|
@@ -3221,12 +3692,13 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3221
3692
|
}
|
|
3222
3693
|
async render() {
|
|
3223
3694
|
var _a;
|
|
3224
|
-
return (_a = this.renderPromise) !== null && _a !== void 0 ? _a : (this.renderPromise = (async () => {
|
|
3225
|
-
|
|
3695
|
+
return ((_a = this.renderPromise) !== null && _a !== void 0 ? _a : (this.renderPromise = (async () => {
|
|
3696
|
+
const event = this.beforeRenderEvent;
|
|
3697
|
+
if (this.dispatchEvent(event)) {
|
|
3226
3698
|
await nextAnimationFrame();
|
|
3227
|
-
|
|
3699
|
+
await event.detail.render(this);
|
|
3228
3700
|
}
|
|
3229
|
-
})());
|
|
3701
|
+
})()));
|
|
3230
3702
|
}
|
|
3231
3703
|
disconnect() {
|
|
3232
3704
|
try {
|
|
@@ -3235,13 +3707,13 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3235
3707
|
catch (_a) { }
|
|
3236
3708
|
}
|
|
3237
3709
|
removeDuplicateTargetChildren() {
|
|
3238
|
-
this.duplicateChildren.forEach(c => c.remove());
|
|
3710
|
+
this.duplicateChildren.forEach((c) => c.remove());
|
|
3239
3711
|
}
|
|
3240
3712
|
get duplicateChildren() {
|
|
3241
3713
|
var _a;
|
|
3242
|
-
const existingChildren = this.targetElements.flatMap(e => [...e.children]).filter(c => !!c.id);
|
|
3243
|
-
const newChildrenIds = [...(_a = this.templateContent) === null || _a === void 0 ? void 0 : _a.children].filter(c => !!c.id).map(c => c.id);
|
|
3244
|
-
return existingChildren.filter(c => newChildrenIds.includes(c.id));
|
|
3714
|
+
const existingChildren = this.targetElements.flatMap((e) => [...e.children]).filter((c) => !!c.id);
|
|
3715
|
+
const newChildrenIds = [...(((_a = this.templateContent) === null || _a === void 0 ? void 0 : _a.children) || [])].filter((c) => !!c.id).map((c) => c.id);
|
|
3716
|
+
return existingChildren.filter((c) => newChildrenIds.includes(c.id));
|
|
3245
3717
|
}
|
|
3246
3718
|
get performAction() {
|
|
3247
3719
|
if (this.action) {
|
|
@@ -3268,7 +3740,12 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3268
3740
|
return this.templateElement.content.cloneNode(true);
|
|
3269
3741
|
}
|
|
3270
3742
|
get templateElement() {
|
|
3271
|
-
if (this.firstElementChild
|
|
3743
|
+
if (this.firstElementChild === null) {
|
|
3744
|
+
const template = this.ownerDocument.createElement("template");
|
|
3745
|
+
this.appendChild(template);
|
|
3746
|
+
return template;
|
|
3747
|
+
}
|
|
3748
|
+
else if (this.firstElementChild instanceof HTMLTemplateElement) {
|
|
3272
3749
|
return this.firstElementChild;
|
|
3273
3750
|
}
|
|
3274
3751
|
this.raise("first child element must be a <template> element");
|
|
@@ -3290,7 +3767,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3290
3767
|
return (_b = ((_a = this.outerHTML.match(/<[^>]+>/)) !== null && _a !== void 0 ? _a : [])[0]) !== null && _b !== void 0 ? _b : "<turbo-stream>";
|
|
3291
3768
|
}
|
|
3292
3769
|
get beforeRenderEvent() {
|
|
3293
|
-
return new CustomEvent("turbo:before-stream-render", {
|
|
3770
|
+
return new CustomEvent("turbo:before-stream-render", {
|
|
3771
|
+
bubbles: true,
|
|
3772
|
+
cancelable: true,
|
|
3773
|
+
detail: { newStream: this, render: StreamElement.renderElement },
|
|
3774
|
+
});
|
|
3294
3775
|
}
|
|
3295
3776
|
get targetElementsById() {
|
|
3296
3777
|
var _a;
|
|
@@ -3314,9 +3795,35 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3314
3795
|
}
|
|
3315
3796
|
}
|
|
3316
3797
|
|
|
3798
|
+
class StreamSourceElement extends HTMLElement {
|
|
3799
|
+
constructor() {
|
|
3800
|
+
super(...arguments);
|
|
3801
|
+
this.streamSource = null;
|
|
3802
|
+
}
|
|
3803
|
+
connectedCallback() {
|
|
3804
|
+
this.streamSource = this.src.match(/^ws{1,2}:/) ? new WebSocket(this.src) : new EventSource(this.src);
|
|
3805
|
+
connectStreamSource(this.streamSource);
|
|
3806
|
+
}
|
|
3807
|
+
disconnectedCallback() {
|
|
3808
|
+
if (this.streamSource) {
|
|
3809
|
+
disconnectStreamSource(this.streamSource);
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
get src() {
|
|
3813
|
+
return this.getAttribute("src") || "";
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3816
|
+
|
|
3317
3817
|
FrameElement.delegateConstructor = FrameController;
|
|
3318
|
-
customElements.
|
|
3319
|
-
|
|
3818
|
+
if (customElements.get("turbo-frame") === undefined) {
|
|
3819
|
+
customElements.define("turbo-frame", FrameElement);
|
|
3820
|
+
}
|
|
3821
|
+
if (customElements.get("turbo-stream") === undefined) {
|
|
3822
|
+
customElements.define("turbo-stream", StreamElement);
|
|
3823
|
+
}
|
|
3824
|
+
if (customElements.get("turbo-stream-source") === undefined) {
|
|
3825
|
+
customElements.define("turbo-stream-source", StreamSourceElement);
|
|
3826
|
+
}
|
|
3320
3827
|
|
|
3321
3828
|
(() => {
|
|
3322
3829
|
let element = document.currentScript;
|
|
@@ -3324,7 +3831,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3324
3831
|
return;
|
|
3325
3832
|
if (element.hasAttribute("data-turbo-suppress-warning"))
|
|
3326
3833
|
return;
|
|
3327
|
-
|
|
3834
|
+
element = element.parentElement;
|
|
3835
|
+
while (element) {
|
|
3328
3836
|
if (element == document.body) {
|
|
3329
3837
|
return console.warn(unindent `
|
|
3330
3838
|
You are loading Turbo from a <script> element inside the <body> element. This is probably not what you meant to do!
|
|
@@ -3337,14 +3845,21 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3337
3845
|
Suppress this warning by adding a "data-turbo-suppress-warning" attribute to: %s
|
|
3338
3846
|
`, element.outerHTML);
|
|
3339
3847
|
}
|
|
3848
|
+
element = element.parentElement;
|
|
3340
3849
|
}
|
|
3341
3850
|
})();
|
|
3342
3851
|
|
|
3343
3852
|
window.Turbo = Turbo;
|
|
3344
3853
|
start();
|
|
3345
3854
|
|
|
3855
|
+
exports.FrameElement = FrameElement;
|
|
3856
|
+
exports.FrameRenderer = FrameRenderer;
|
|
3346
3857
|
exports.PageRenderer = PageRenderer;
|
|
3347
3858
|
exports.PageSnapshot = PageSnapshot;
|
|
3859
|
+
exports.StreamActions = StreamActions;
|
|
3860
|
+
exports.StreamElement = StreamElement;
|
|
3861
|
+
exports.StreamSourceElement = StreamSourceElement;
|
|
3862
|
+
exports.cache = cache;
|
|
3348
3863
|
exports.clearCache = clearCache;
|
|
3349
3864
|
exports.connectStreamSource = connectStreamSource;
|
|
3350
3865
|
exports.disconnectStreamSource = disconnectStreamSource;
|
|
@@ -3353,10 +3868,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3353
3868
|
exports.renderStreamMessage = renderStreamMessage;
|
|
3354
3869
|
exports.session = session;
|
|
3355
3870
|
exports.setConfirmMethod = setConfirmMethod;
|
|
3871
|
+
exports.setFormMode = setFormMode;
|
|
3356
3872
|
exports.setProgressBarDelay = setProgressBarDelay;
|
|
3357
3873
|
exports.start = start;
|
|
3358
3874
|
exports.visit = visit;
|
|
3359
3875
|
|
|
3360
3876
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3361
3877
|
|
|
3362
|
-
}))
|
|
3878
|
+
}));
|