@hotwired/turbo 7.1.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/turbo.es2017-esm.js +1284 -655
- package/dist/turbo.es2017-umd.js +1298 -662
- 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 +20 -9
- package/dist/types/core/drive/head_snapshot.d.ts +6 -6
- package/dist/types/core/drive/history.d.ts +4 -4
- package/dist/types/core/drive/navigator.d.ts +2 -2
- package/dist/types/core/drive/page_renderer.d.ts +12 -7
- package/dist/types/core/drive/page_view.d.ts +10 -8
- 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 -6
- package/dist/types/core/errors.d.ts +2 -0
- package/dist/types/core/frames/frame_controller.d.ts +56 -26
- package/dist/types/core/frames/frame_redirector.d.ts +10 -8
- package/dist/types/core/frames/frame_renderer.d.ts +8 -1
- package/dist/types/core/frames/frame_view.d.ts +3 -2
- package/dist/types/core/frames/link_interceptor.d.ts +3 -3
- package/dist/types/core/index.d.ts +12 -3
- package/dist/types/core/native/adapter.d.ts +2 -1
- package/dist/types/core/native/browser_adapter.d.ts +17 -8
- package/dist/types/core/renderer.d.ts +12 -6
- package/dist/types/core/session.d.ts +72 -17
- package/dist/types/core/snapshot.d.ts +6 -3
- 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 +3 -4
- package/dist/types/core/url.d.ts +1 -1
- package/dist/types/core/view.d.ts +13 -7
- package/dist/types/elements/frame_element.d.ts +12 -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 +18 -4
- package/dist/types/http/index.d.ts +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/observers/appearance_observer.d.ts +6 -6
- package/dist/types/observers/cache_observer.d.ts +5 -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/custom-elements-native-shim.d.ts +1 -0
- 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_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 +7 -51
- 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/dom_test_case.d.ts +1 -2
- package/dist/types/tests/helpers/page.d.ts +60 -0
- package/dist/types/tests/integration/ujs_tests.d.ts +1 -0
- package/dist/types/tests/unit/deprecated_adapter_support_tests.d.ts +1 -0
- package/dist/types/tests/unit/export_tests.d.ts +1 -0
- package/dist/types/tests/unit/stream_element_tests.d.ts +0 -10
- package/dist/types/util.d.ts +15 -3
- package/package.json +32 -13
- package/CHANGELOG.md +0 -3
- package/dist/types/core/frames/form_interceptor.d.ts +0 -12
- 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/intern_test_case.d.ts +0 -20
- 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/types/tests/unit/deprecated_adapter_support_test.d.ts +0 -24
- package/dist/types/tests/unit/index.d.ts +0 -2
package/dist/turbo.es2017-umd.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Turbo 7.
|
|
3
|
-
Copyright ©
|
|
2
|
+
Turbo 7.3.0
|
|
3
|
+
Copyright © 2023 37signals 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;
|
|
@@ -93,40 +93,37 @@ Copyright © 2021 Basecamp, LLC
|
|
|
93
93
|
(function () {
|
|
94
94
|
if ("submitter" in Event.prototype)
|
|
95
95
|
return;
|
|
96
|
-
let prototype;
|
|
96
|
+
let prototype = window.Event.prototype;
|
|
97
97
|
if ("SubmitEvent" in window && /Apple Computer/.test(navigator.vendor)) {
|
|
98
98
|
prototype = window.SubmitEvent.prototype;
|
|
99
99
|
}
|
|
100
100
|
else if ("SubmitEvent" in window) {
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
|
-
else {
|
|
104
|
-
prototype = window.Event.prototype;
|
|
105
|
-
}
|
|
106
103
|
addEventListener("click", clickCaptured, true);
|
|
107
104
|
Object.defineProperty(prototype, "submitter", {
|
|
108
105
|
get() {
|
|
109
106
|
if (this.type == "submit" && this.target instanceof HTMLFormElement) {
|
|
110
107
|
return submittersByForm.get(this.target);
|
|
111
108
|
}
|
|
112
|
-
}
|
|
109
|
+
},
|
|
113
110
|
});
|
|
114
111
|
})();
|
|
115
112
|
|
|
116
|
-
|
|
113
|
+
exports.FrameLoadingStyle = void 0;
|
|
117
114
|
(function (FrameLoadingStyle) {
|
|
118
115
|
FrameLoadingStyle["eager"] = "eager";
|
|
119
116
|
FrameLoadingStyle["lazy"] = "lazy";
|
|
120
|
-
})(FrameLoadingStyle || (FrameLoadingStyle = {}));
|
|
117
|
+
})(exports.FrameLoadingStyle || (exports.FrameLoadingStyle = {}));
|
|
121
118
|
class FrameElement extends HTMLElement {
|
|
119
|
+
static get observedAttributes() {
|
|
120
|
+
return ["disabled", "complete", "loading", "src"];
|
|
121
|
+
}
|
|
122
122
|
constructor() {
|
|
123
123
|
super();
|
|
124
124
|
this.loaded = Promise.resolve();
|
|
125
125
|
this.delegate = new FrameElement.delegateConstructor(this);
|
|
126
126
|
}
|
|
127
|
-
static get observedAttributes() {
|
|
128
|
-
return ["disabled", "loading", "src"];
|
|
129
|
-
}
|
|
130
127
|
connectedCallback() {
|
|
131
128
|
this.delegate.connect();
|
|
132
129
|
}
|
|
@@ -134,14 +131,15 @@ Copyright © 2021 Basecamp, LLC
|
|
|
134
131
|
this.delegate.disconnect();
|
|
135
132
|
}
|
|
136
133
|
reload() {
|
|
137
|
-
|
|
138
|
-
this.src = null;
|
|
139
|
-
this.src = src;
|
|
134
|
+
return this.delegate.sourceURLReloaded();
|
|
140
135
|
}
|
|
141
136
|
attributeChangedCallback(name) {
|
|
142
137
|
if (name == "loading") {
|
|
143
138
|
this.delegate.loadingStyleChanged();
|
|
144
139
|
}
|
|
140
|
+
else if (name == "complete") {
|
|
141
|
+
this.delegate.completeChanged();
|
|
142
|
+
}
|
|
145
143
|
else if (name == "src") {
|
|
146
144
|
this.delegate.sourceURLChanged();
|
|
147
145
|
}
|
|
@@ -206,8 +204,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
206
204
|
}
|
|
207
205
|
function frameLoadingStyleFromString(style) {
|
|
208
206
|
switch (style.toLowerCase()) {
|
|
209
|
-
case "lazy":
|
|
210
|
-
|
|
207
|
+
case "lazy":
|
|
208
|
+
return exports.FrameLoadingStyle.lazy;
|
|
209
|
+
default:
|
|
210
|
+
return exports.FrameLoadingStyle.eager;
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
213
|
|
|
@@ -219,7 +219,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
219
219
|
if (url.hash) {
|
|
220
220
|
return url.hash.slice(1);
|
|
221
221
|
}
|
|
222
|
-
else if (anchorMatch = url.href.match(/#(.*)$/)) {
|
|
222
|
+
else if ((anchorMatch = url.href.match(/#(.*)$/))) {
|
|
223
223
|
return anchorMatch[1];
|
|
224
224
|
}
|
|
225
225
|
}
|
|
@@ -231,7 +231,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
231
231
|
return (getLastPathComponent(url).match(/\.[^.]*$/) || [])[0] || "";
|
|
232
232
|
}
|
|
233
233
|
function isHTML(url) {
|
|
234
|
-
return !!getExtension(url).match(/^(?:|\.(?:htm|html|xhtml))$/);
|
|
234
|
+
return !!getExtension(url).match(/^(?:|\.(?:htm|html|xhtml|php))$/);
|
|
235
235
|
}
|
|
236
236
|
function isPrefixedBy(baseURL, url) {
|
|
237
237
|
const prefix = getPrefix(url);
|
|
@@ -242,9 +242,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
242
242
|
}
|
|
243
243
|
function getRequestURL(url) {
|
|
244
244
|
const anchor = getAnchor(url);
|
|
245
|
-
return anchor != null
|
|
246
|
-
? url.href.slice(0, -(anchor.length + 1))
|
|
247
|
-
: url.href;
|
|
245
|
+
return anchor != null ? url.href.slice(0, -(anchor.length + 1)) : url.href;
|
|
248
246
|
}
|
|
249
247
|
function toCacheKey(url) {
|
|
250
248
|
return getRequestURL(url);
|
|
@@ -312,8 +310,39 @@ Copyright © 2021 Basecamp, LLC
|
|
|
312
310
|
}
|
|
313
311
|
}
|
|
314
312
|
|
|
313
|
+
function activateScriptElement(element) {
|
|
314
|
+
if (element.getAttribute("data-turbo-eval") == "false") {
|
|
315
|
+
return element;
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
const createdScriptElement = document.createElement("script");
|
|
319
|
+
const cspNonce = getMetaContent("csp-nonce");
|
|
320
|
+
if (cspNonce) {
|
|
321
|
+
createdScriptElement.nonce = cspNonce;
|
|
322
|
+
}
|
|
323
|
+
createdScriptElement.textContent = element.textContent;
|
|
324
|
+
createdScriptElement.async = false;
|
|
325
|
+
copyElementAttributes(createdScriptElement, element);
|
|
326
|
+
return createdScriptElement;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function copyElementAttributes(destinationElement, sourceElement) {
|
|
330
|
+
for (const { name, value } of sourceElement.attributes) {
|
|
331
|
+
destinationElement.setAttribute(name, value);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function createDocumentFragment(html) {
|
|
335
|
+
const template = document.createElement("template");
|
|
336
|
+
template.innerHTML = html;
|
|
337
|
+
return template.content;
|
|
338
|
+
}
|
|
315
339
|
function dispatch(eventName, { target, cancelable, detail } = {}) {
|
|
316
|
-
const event = new CustomEvent(eventName, {
|
|
340
|
+
const event = new CustomEvent(eventName, {
|
|
341
|
+
cancelable,
|
|
342
|
+
bubbles: true,
|
|
343
|
+
composed: true,
|
|
344
|
+
detail,
|
|
345
|
+
});
|
|
317
346
|
if (target && target.isConnected) {
|
|
318
347
|
target.dispatchEvent(event);
|
|
319
348
|
}
|
|
@@ -323,10 +352,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
323
352
|
return event;
|
|
324
353
|
}
|
|
325
354
|
function nextAnimationFrame() {
|
|
326
|
-
return new Promise(resolve => requestAnimationFrame(() => resolve()));
|
|
355
|
+
return new Promise((resolve) => requestAnimationFrame(() => resolve()));
|
|
327
356
|
}
|
|
328
357
|
function nextEventLoopTick() {
|
|
329
|
-
return new Promise(resolve => setTimeout(() => resolve(), 0));
|
|
358
|
+
return new Promise((resolve) => setTimeout(() => resolve(), 0));
|
|
330
359
|
}
|
|
331
360
|
function nextMicrotask() {
|
|
332
361
|
return Promise.resolve();
|
|
@@ -338,7 +367,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
338
367
|
const lines = interpolate(strings, values).replace(/^\n/, "").split("\n");
|
|
339
368
|
const match = lines[0].match(/^\s+/);
|
|
340
369
|
const indent = match ? match[0].length : 0;
|
|
341
|
-
return lines.map(line => line.slice(indent)).join("\n");
|
|
370
|
+
return lines.map((line) => line.slice(indent)).join("\n");
|
|
342
371
|
}
|
|
343
372
|
function interpolate(strings, values) {
|
|
344
373
|
return strings.reduce((result, string, i) => {
|
|
@@ -347,7 +376,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
347
376
|
}, "");
|
|
348
377
|
}
|
|
349
378
|
function uuid() {
|
|
350
|
-
return Array.
|
|
379
|
+
return Array.from({ length: 36 })
|
|
380
|
+
.map((_, i) => {
|
|
351
381
|
if (i == 8 || i == 13 || i == 18 || i == 23) {
|
|
352
382
|
return "-";
|
|
353
383
|
}
|
|
@@ -360,15 +390,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
360
390
|
else {
|
|
361
391
|
return Math.floor(Math.random() * 15).toString(16);
|
|
362
392
|
}
|
|
363
|
-
})
|
|
393
|
+
})
|
|
394
|
+
.join("");
|
|
364
395
|
}
|
|
365
396
|
function getAttribute(attributeName, ...elements) {
|
|
366
|
-
for (const value of elements.map(element => element === null || element === void 0 ? void 0 : element.getAttribute(attributeName))) {
|
|
397
|
+
for (const value of elements.map((element) => element === null || element === void 0 ? void 0 : element.getAttribute(attributeName))) {
|
|
367
398
|
if (typeof value == "string")
|
|
368
399
|
return value;
|
|
369
400
|
}
|
|
370
401
|
return null;
|
|
371
402
|
}
|
|
403
|
+
function hasAttribute(attributeName, ...elements) {
|
|
404
|
+
return elements.some((element) => element && element.hasAttribute(attributeName));
|
|
405
|
+
}
|
|
372
406
|
function markAsBusy(...elements) {
|
|
373
407
|
for (const element of elements) {
|
|
374
408
|
if (element.localName == "turbo-frame") {
|
|
@@ -385,6 +419,58 @@ Copyright © 2021 Basecamp, LLC
|
|
|
385
419
|
element.removeAttribute("aria-busy");
|
|
386
420
|
}
|
|
387
421
|
}
|
|
422
|
+
function waitForLoad(element, timeoutInMilliseconds = 2000) {
|
|
423
|
+
return new Promise((resolve) => {
|
|
424
|
+
const onComplete = () => {
|
|
425
|
+
element.removeEventListener("error", onComplete);
|
|
426
|
+
element.removeEventListener("load", onComplete);
|
|
427
|
+
resolve();
|
|
428
|
+
};
|
|
429
|
+
element.addEventListener("load", onComplete, { once: true });
|
|
430
|
+
element.addEventListener("error", onComplete, { once: true });
|
|
431
|
+
setTimeout(resolve, timeoutInMilliseconds);
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
function getHistoryMethodForAction(action) {
|
|
435
|
+
switch (action) {
|
|
436
|
+
case "replace":
|
|
437
|
+
return history.replaceState;
|
|
438
|
+
case "advance":
|
|
439
|
+
case "restore":
|
|
440
|
+
return history.pushState;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
function isAction(action) {
|
|
444
|
+
return action == "advance" || action == "replace" || action == "restore";
|
|
445
|
+
}
|
|
446
|
+
function getVisitAction(...elements) {
|
|
447
|
+
const action = getAttribute("data-turbo-action", ...elements);
|
|
448
|
+
return isAction(action) ? action : null;
|
|
449
|
+
}
|
|
450
|
+
function getMetaElement(name) {
|
|
451
|
+
return document.querySelector(`meta[name="${name}"]`);
|
|
452
|
+
}
|
|
453
|
+
function getMetaContent(name) {
|
|
454
|
+
const element = getMetaElement(name);
|
|
455
|
+
return element && element.content;
|
|
456
|
+
}
|
|
457
|
+
function setMetaContent(name, content) {
|
|
458
|
+
let element = getMetaElement(name);
|
|
459
|
+
if (!element) {
|
|
460
|
+
element = document.createElement("meta");
|
|
461
|
+
element.setAttribute("name", name);
|
|
462
|
+
document.head.appendChild(element);
|
|
463
|
+
}
|
|
464
|
+
element.setAttribute("content", content);
|
|
465
|
+
return element;
|
|
466
|
+
}
|
|
467
|
+
function findClosestRecursively(element, selector) {
|
|
468
|
+
var _a;
|
|
469
|
+
if (element instanceof Element) {
|
|
470
|
+
return (element.closest(selector) ||
|
|
471
|
+
findClosestRecursively(element.assignedSlot || ((_a = element.getRootNode()) === null || _a === void 0 ? void 0 : _a.host), selector));
|
|
472
|
+
}
|
|
473
|
+
}
|
|
388
474
|
|
|
389
475
|
var FetchMethod;
|
|
390
476
|
(function (FetchMethod) {
|
|
@@ -396,17 +482,22 @@ Copyright © 2021 Basecamp, LLC
|
|
|
396
482
|
})(FetchMethod || (FetchMethod = {}));
|
|
397
483
|
function fetchMethodFromString(method) {
|
|
398
484
|
switch (method.toLowerCase()) {
|
|
399
|
-
case "get":
|
|
400
|
-
|
|
401
|
-
case "
|
|
402
|
-
|
|
403
|
-
case "
|
|
485
|
+
case "get":
|
|
486
|
+
return FetchMethod.get;
|
|
487
|
+
case "post":
|
|
488
|
+
return FetchMethod.post;
|
|
489
|
+
case "put":
|
|
490
|
+
return FetchMethod.put;
|
|
491
|
+
case "patch":
|
|
492
|
+
return FetchMethod.patch;
|
|
493
|
+
case "delete":
|
|
494
|
+
return FetchMethod.delete;
|
|
404
495
|
}
|
|
405
496
|
}
|
|
406
497
|
class FetchRequest {
|
|
407
|
-
constructor(delegate, method, location, body = new URLSearchParams, target = null) {
|
|
408
|
-
this.abortController = new AbortController;
|
|
409
|
-
this.resolveRequestPromise = (
|
|
498
|
+
constructor(delegate, method, location, body = new URLSearchParams(), target = null) {
|
|
499
|
+
this.abortController = new AbortController();
|
|
500
|
+
this.resolveRequestPromise = (_value) => { };
|
|
410
501
|
this.delegate = delegate;
|
|
411
502
|
this.method = method;
|
|
412
503
|
this.headers = this.defaultHeaders;
|
|
@@ -427,9 +518,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
427
518
|
this.abortController.abort();
|
|
428
519
|
}
|
|
429
520
|
async perform() {
|
|
430
|
-
var _a, _b;
|
|
431
521
|
const { fetchOptions } = this;
|
|
432
|
-
|
|
522
|
+
this.delegate.prepareRequest(this);
|
|
433
523
|
await this.allowRequestToBeIntercepted(fetchOptions);
|
|
434
524
|
try {
|
|
435
525
|
this.delegate.requestStarted(this);
|
|
@@ -437,8 +527,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
437
527
|
return await this.receive(response);
|
|
438
528
|
}
|
|
439
529
|
catch (error) {
|
|
440
|
-
if (error.name !==
|
|
441
|
-
this.
|
|
530
|
+
if (error.name !== "AbortError") {
|
|
531
|
+
if (this.willDelegateErrorHandling(error)) {
|
|
532
|
+
this.delegate.requestErrored(this, error);
|
|
533
|
+
}
|
|
442
534
|
throw error;
|
|
443
535
|
}
|
|
444
536
|
}
|
|
@@ -448,7 +540,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
448
540
|
}
|
|
449
541
|
async receive(response) {
|
|
450
542
|
const fetchResponse = new FetchResponse(response);
|
|
451
|
-
const event = dispatch("turbo:before-fetch-response", {
|
|
543
|
+
const event = dispatch("turbo:before-fetch-response", {
|
|
544
|
+
cancelable: true,
|
|
545
|
+
detail: { fetchResponse },
|
|
546
|
+
target: this.target,
|
|
547
|
+
});
|
|
452
548
|
if (event.defaultPrevented) {
|
|
453
549
|
this.delegate.requestPreventedHandlingResponse(this, fetchResponse);
|
|
454
550
|
}
|
|
@@ -467,42 +563,53 @@ Copyright © 2021 Basecamp, LLC
|
|
|
467
563
|
credentials: "same-origin",
|
|
468
564
|
headers: this.headers,
|
|
469
565
|
redirect: "follow",
|
|
470
|
-
body: this.
|
|
566
|
+
body: this.isSafe ? null : this.body,
|
|
471
567
|
signal: this.abortSignal,
|
|
472
|
-
referrer: (_a = this.delegate.referrer) === null || _a === void 0 ? void 0 : _a.href
|
|
568
|
+
referrer: (_a = this.delegate.referrer) === null || _a === void 0 ? void 0 : _a.href,
|
|
473
569
|
};
|
|
474
570
|
}
|
|
475
571
|
get defaultHeaders() {
|
|
476
572
|
return {
|
|
477
|
-
|
|
573
|
+
Accept: "text/html, application/xhtml+xml",
|
|
478
574
|
};
|
|
479
575
|
}
|
|
480
|
-
get
|
|
481
|
-
return this.method
|
|
576
|
+
get isSafe() {
|
|
577
|
+
return this.method === FetchMethod.get;
|
|
482
578
|
}
|
|
483
579
|
get abortSignal() {
|
|
484
580
|
return this.abortController.signal;
|
|
485
581
|
}
|
|
582
|
+
acceptResponseType(mimeType) {
|
|
583
|
+
this.headers["Accept"] = [mimeType, this.headers["Accept"]].join(", ");
|
|
584
|
+
}
|
|
486
585
|
async allowRequestToBeIntercepted(fetchOptions) {
|
|
487
|
-
const requestInterception = new Promise(resolve => this.resolveRequestPromise = resolve);
|
|
586
|
+
const requestInterception = new Promise((resolve) => (this.resolveRequestPromise = resolve));
|
|
488
587
|
const event = dispatch("turbo:before-fetch-request", {
|
|
489
588
|
cancelable: true,
|
|
490
589
|
detail: {
|
|
491
590
|
fetchOptions,
|
|
492
591
|
url: this.url,
|
|
493
|
-
resume: this.resolveRequestPromise
|
|
592
|
+
resume: this.resolveRequestPromise,
|
|
494
593
|
},
|
|
495
|
-
target: this.target
|
|
594
|
+
target: this.target,
|
|
496
595
|
});
|
|
497
596
|
if (event.defaultPrevented)
|
|
498
597
|
await requestInterception;
|
|
499
598
|
}
|
|
599
|
+
willDelegateErrorHandling(error) {
|
|
600
|
+
const event = dispatch("turbo:fetch-request-error", {
|
|
601
|
+
target: this.target,
|
|
602
|
+
cancelable: true,
|
|
603
|
+
detail: { request: this, error: error },
|
|
604
|
+
});
|
|
605
|
+
return !event.defaultPrevented;
|
|
606
|
+
}
|
|
500
607
|
}
|
|
501
608
|
|
|
502
609
|
class AppearanceObserver {
|
|
503
610
|
constructor(delegate, element) {
|
|
504
611
|
this.started = false;
|
|
505
|
-
this.intersect = entries => {
|
|
612
|
+
this.intersect = (entries) => {
|
|
506
613
|
const lastEntry = entries.slice(-1)[0];
|
|
507
614
|
if (lastEntry === null || lastEntry === void 0 ? void 0 : lastEntry.isIntersecting) {
|
|
508
615
|
this.delegate.elementAppearedInViewport(this.element);
|
|
@@ -527,40 +634,29 @@ Copyright © 2021 Basecamp, LLC
|
|
|
527
634
|
}
|
|
528
635
|
|
|
529
636
|
class StreamMessage {
|
|
530
|
-
constructor(html) {
|
|
531
|
-
this.templateElement = document.createElement("template");
|
|
532
|
-
this.templateElement.innerHTML = html;
|
|
533
|
-
}
|
|
534
637
|
static wrap(message) {
|
|
535
638
|
if (typeof message == "string") {
|
|
536
|
-
return new this(message);
|
|
639
|
+
return new this(createDocumentFragment(message));
|
|
537
640
|
}
|
|
538
641
|
else {
|
|
539
642
|
return message;
|
|
540
643
|
}
|
|
541
644
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
for (const element of this.foreignElements) {
|
|
545
|
-
fragment.appendChild(document.importNode(element, true));
|
|
546
|
-
}
|
|
547
|
-
return fragment;
|
|
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);
|
|
645
|
+
constructor(fragment) {
|
|
646
|
+
this.fragment = importStreamElements(fragment);
|
|
561
647
|
}
|
|
562
648
|
}
|
|
563
649
|
StreamMessage.contentType = "text/vnd.turbo-stream.html";
|
|
650
|
+
function importStreamElements(fragment) {
|
|
651
|
+
for (const element of fragment.querySelectorAll("turbo-stream")) {
|
|
652
|
+
const streamElement = document.importNode(element, true);
|
|
653
|
+
for (const inertScriptElement of streamElement.templateElement.content.querySelectorAll("script")) {
|
|
654
|
+
inertScriptElement.replaceWith(activateScriptElement(inertScriptElement));
|
|
655
|
+
}
|
|
656
|
+
element.replaceWith(streamElement);
|
|
657
|
+
}
|
|
658
|
+
return fragment;
|
|
659
|
+
}
|
|
564
660
|
|
|
565
661
|
var FormSubmissionState;
|
|
566
662
|
(function (FormSubmissionState) {
|
|
@@ -579,12 +675,18 @@ Copyright © 2021 Basecamp, LLC
|
|
|
579
675
|
})(FormEnctype || (FormEnctype = {}));
|
|
580
676
|
function formEnctypeFromString(encoding) {
|
|
581
677
|
switch (encoding.toLowerCase()) {
|
|
582
|
-
case FormEnctype.multipart:
|
|
583
|
-
|
|
584
|
-
|
|
678
|
+
case FormEnctype.multipart:
|
|
679
|
+
return FormEnctype.multipart;
|
|
680
|
+
case FormEnctype.plain:
|
|
681
|
+
return FormEnctype.plain;
|
|
682
|
+
default:
|
|
683
|
+
return FormEnctype.urlEncoded;
|
|
585
684
|
}
|
|
586
685
|
}
|
|
587
686
|
class FormSubmission {
|
|
687
|
+
static confirmMethod(message, _element, _submitter) {
|
|
688
|
+
return Promise.resolve(confirm(message));
|
|
689
|
+
}
|
|
588
690
|
constructor(delegate, formElement, submitter, mustRedirect = false) {
|
|
589
691
|
this.state = FormSubmissionState.initialized;
|
|
590
692
|
this.delegate = delegate;
|
|
@@ -598,9 +700,6 @@ Copyright © 2021 Basecamp, LLC
|
|
|
598
700
|
this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
|
|
599
701
|
this.mustRedirect = mustRedirect;
|
|
600
702
|
}
|
|
601
|
-
static confirmMethod(message, element) {
|
|
602
|
-
return confirm(message);
|
|
603
|
-
}
|
|
604
703
|
get method() {
|
|
605
704
|
var _a;
|
|
606
705
|
const method = ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formmethod")) || this.formElement.getAttribute("method") || "";
|
|
@@ -608,8 +707,13 @@ Copyright © 2021 Basecamp, LLC
|
|
|
608
707
|
}
|
|
609
708
|
get action() {
|
|
610
709
|
var _a;
|
|
611
|
-
const formElementAction = typeof this.formElement.action ===
|
|
612
|
-
|
|
710
|
+
const formElementAction = typeof this.formElement.action === "string" ? this.formElement.action : null;
|
|
711
|
+
if ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.hasAttribute("formaction")) {
|
|
712
|
+
return this.submitter.getAttribute("formaction") || "";
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
return this.formElement.getAttribute("action") || formElementAction || "";
|
|
716
|
+
}
|
|
613
717
|
}
|
|
614
718
|
get body() {
|
|
615
719
|
if (this.enctype == FormEnctype.urlEncoded || this.method == FetchMethod.get) {
|
|
@@ -623,24 +727,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
623
727
|
var _a;
|
|
624
728
|
return formEnctypeFromString(((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formenctype")) || this.formElement.enctype);
|
|
625
729
|
}
|
|
626
|
-
get
|
|
627
|
-
return this.fetchRequest.
|
|
730
|
+
get isSafe() {
|
|
731
|
+
return this.fetchRequest.isSafe;
|
|
628
732
|
}
|
|
629
733
|
get stringFormData() {
|
|
630
734
|
return [...this.formData].reduce((entries, [name, value]) => {
|
|
631
735
|
return entries.concat(typeof value == "string" ? [[name, value]] : []);
|
|
632
736
|
}, []);
|
|
633
737
|
}
|
|
634
|
-
get confirmationMessage() {
|
|
635
|
-
return this.formElement.getAttribute("data-turbo-confirm");
|
|
636
|
-
}
|
|
637
|
-
get needsConfirmation() {
|
|
638
|
-
return this.confirmationMessage !== null;
|
|
639
|
-
}
|
|
640
738
|
async start() {
|
|
641
739
|
const { initialized, requesting } = FormSubmissionState;
|
|
642
|
-
|
|
643
|
-
|
|
740
|
+
const confirmationMessage = getAttribute("data-turbo-confirm", this.submitter, this.formElement);
|
|
741
|
+
if (typeof confirmationMessage === "string") {
|
|
742
|
+
const answer = await FormSubmission.confirmMethod(confirmationMessage, this.formElement, this.submitter);
|
|
644
743
|
if (!answer) {
|
|
645
744
|
return;
|
|
646
745
|
}
|
|
@@ -658,20 +757,26 @@ Copyright © 2021 Basecamp, LLC
|
|
|
658
757
|
return true;
|
|
659
758
|
}
|
|
660
759
|
}
|
|
661
|
-
|
|
662
|
-
if (!request.
|
|
760
|
+
prepareRequest(request) {
|
|
761
|
+
if (!request.isSafe) {
|
|
663
762
|
const token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token");
|
|
664
763
|
if (token) {
|
|
665
|
-
headers["X-CSRF-Token"] = token;
|
|
764
|
+
request.headers["X-CSRF-Token"] = token;
|
|
666
765
|
}
|
|
667
|
-
|
|
766
|
+
}
|
|
767
|
+
if (this.requestAcceptsTurboStreamResponse(request)) {
|
|
768
|
+
request.acceptResponseType(StreamMessage.contentType);
|
|
668
769
|
}
|
|
669
770
|
}
|
|
670
|
-
requestStarted(
|
|
771
|
+
requestStarted(_request) {
|
|
671
772
|
var _a;
|
|
672
773
|
this.state = FormSubmissionState.waiting;
|
|
673
774
|
(_a = this.submitter) === null || _a === void 0 ? void 0 : _a.setAttribute("disabled", "");
|
|
674
|
-
|
|
775
|
+
this.setSubmitsWith();
|
|
776
|
+
dispatch("turbo:submit-start", {
|
|
777
|
+
target: this.formElement,
|
|
778
|
+
detail: { formSubmission: this },
|
|
779
|
+
});
|
|
675
780
|
this.delegate.formSubmissionStarted(this);
|
|
676
781
|
}
|
|
677
782
|
requestPreventedHandlingResponse(request, response) {
|
|
@@ -699,23 +804,58 @@ Copyright © 2021 Basecamp, LLC
|
|
|
699
804
|
this.result = { success: false, error };
|
|
700
805
|
this.delegate.formSubmissionErrored(this, error);
|
|
701
806
|
}
|
|
702
|
-
requestFinished(
|
|
807
|
+
requestFinished(_request) {
|
|
703
808
|
var _a;
|
|
704
809
|
this.state = FormSubmissionState.stopped;
|
|
705
810
|
(_a = this.submitter) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled");
|
|
706
|
-
|
|
811
|
+
this.resetSubmitterText();
|
|
812
|
+
dispatch("turbo:submit-end", {
|
|
813
|
+
target: this.formElement,
|
|
814
|
+
detail: Object.assign({ formSubmission: this }, this.result),
|
|
815
|
+
});
|
|
707
816
|
this.delegate.formSubmissionFinished(this);
|
|
708
817
|
}
|
|
818
|
+
setSubmitsWith() {
|
|
819
|
+
if (!this.submitter || !this.submitsWith)
|
|
820
|
+
return;
|
|
821
|
+
if (this.submitter.matches("button")) {
|
|
822
|
+
this.originalSubmitText = this.submitter.innerHTML;
|
|
823
|
+
this.submitter.innerHTML = this.submitsWith;
|
|
824
|
+
}
|
|
825
|
+
else if (this.submitter.matches("input")) {
|
|
826
|
+
const input = this.submitter;
|
|
827
|
+
this.originalSubmitText = input.value;
|
|
828
|
+
input.value = this.submitsWith;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
resetSubmitterText() {
|
|
832
|
+
if (!this.submitter || !this.originalSubmitText)
|
|
833
|
+
return;
|
|
834
|
+
if (this.submitter.matches("button")) {
|
|
835
|
+
this.submitter.innerHTML = this.originalSubmitText;
|
|
836
|
+
}
|
|
837
|
+
else if (this.submitter.matches("input")) {
|
|
838
|
+
const input = this.submitter;
|
|
839
|
+
input.value = this.originalSubmitText;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
709
842
|
requestMustRedirect(request) {
|
|
710
|
-
return !request.
|
|
843
|
+
return !request.isSafe && this.mustRedirect;
|
|
844
|
+
}
|
|
845
|
+
requestAcceptsTurboStreamResponse(request) {
|
|
846
|
+
return !request.isSafe || hasAttribute("data-turbo-stream", this.submitter, this.formElement);
|
|
847
|
+
}
|
|
848
|
+
get submitsWith() {
|
|
849
|
+
var _a;
|
|
850
|
+
return (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("data-turbo-submits-with");
|
|
711
851
|
}
|
|
712
852
|
}
|
|
713
853
|
function buildFormData(formElement, submitter) {
|
|
714
854
|
const formData = new FormData(formElement);
|
|
715
855
|
const name = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("name");
|
|
716
856
|
const value = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("value");
|
|
717
|
-
if (name
|
|
718
|
-
formData.append(name, value);
|
|
857
|
+
if (name) {
|
|
858
|
+
formData.append(name, value || "");
|
|
719
859
|
}
|
|
720
860
|
return formData;
|
|
721
861
|
}
|
|
@@ -729,15 +869,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
729
869
|
}
|
|
730
870
|
}
|
|
731
871
|
}
|
|
732
|
-
function getMetaContent(name) {
|
|
733
|
-
const element = document.querySelector(`meta[name="${name}"]`);
|
|
734
|
-
return element && element.content;
|
|
735
|
-
}
|
|
736
872
|
function responseSucceededWithoutRedirect(response) {
|
|
737
873
|
return response.statusCode == 200 && !response.redirected;
|
|
738
874
|
}
|
|
739
875
|
function mergeFormDataEntries(url, entries) {
|
|
740
|
-
const searchParams = new URLSearchParams;
|
|
876
|
+
const searchParams = new URLSearchParams();
|
|
741
877
|
for (const [name, value] of entries) {
|
|
742
878
|
if (value instanceof File)
|
|
743
879
|
continue;
|
|
@@ -751,6 +887,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
751
887
|
constructor(element) {
|
|
752
888
|
this.element = element;
|
|
753
889
|
}
|
|
890
|
+
get activeElement() {
|
|
891
|
+
return this.element.ownerDocument.activeElement;
|
|
892
|
+
}
|
|
754
893
|
get children() {
|
|
755
894
|
return [...this.element.children];
|
|
756
895
|
}
|
|
@@ -764,13 +903,20 @@ Copyright © 2021 Basecamp, LLC
|
|
|
764
903
|
return this.element.isConnected;
|
|
765
904
|
}
|
|
766
905
|
get firstAutofocusableElement() {
|
|
767
|
-
|
|
906
|
+
const inertDisabledOrHidden = "[inert], :disabled, [hidden], details:not([open]), dialog:not([open])";
|
|
907
|
+
for (const element of this.element.querySelectorAll("[autofocus]")) {
|
|
908
|
+
if (element.closest(inertDisabledOrHidden) == null)
|
|
909
|
+
return element;
|
|
910
|
+
else
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
return null;
|
|
768
914
|
}
|
|
769
915
|
get permanentElements() {
|
|
770
|
-
return
|
|
916
|
+
return queryPermanentElementsAll(this.element);
|
|
771
917
|
}
|
|
772
918
|
getPermanentElementById(id) {
|
|
773
|
-
return this.element
|
|
919
|
+
return getPermanentElementById(this.element, id);
|
|
774
920
|
}
|
|
775
921
|
getPermanentElementMapForSnapshot(snapshot) {
|
|
776
922
|
const permanentElementMap = {};
|
|
@@ -784,36 +930,72 @@ Copyright © 2021 Basecamp, LLC
|
|
|
784
930
|
return permanentElementMap;
|
|
785
931
|
}
|
|
786
932
|
}
|
|
933
|
+
function getPermanentElementById(node, id) {
|
|
934
|
+
return node.querySelector(`#${id}[data-turbo-permanent]`);
|
|
935
|
+
}
|
|
936
|
+
function queryPermanentElementsAll(node) {
|
|
937
|
+
return node.querySelectorAll("[id][data-turbo-permanent]");
|
|
938
|
+
}
|
|
787
939
|
|
|
788
|
-
class
|
|
789
|
-
constructor(delegate,
|
|
940
|
+
class FormSubmitObserver {
|
|
941
|
+
constructor(delegate, eventTarget) {
|
|
942
|
+
this.started = false;
|
|
943
|
+
this.submitCaptured = () => {
|
|
944
|
+
this.eventTarget.removeEventListener("submit", this.submitBubbled, false);
|
|
945
|
+
this.eventTarget.addEventListener("submit", this.submitBubbled, false);
|
|
946
|
+
};
|
|
790
947
|
this.submitBubbled = ((event) => {
|
|
791
|
-
|
|
792
|
-
|
|
948
|
+
if (!event.defaultPrevented) {
|
|
949
|
+
const form = event.target instanceof HTMLFormElement ? event.target : undefined;
|
|
793
950
|
const submitter = event.submitter || undefined;
|
|
794
|
-
|
|
795
|
-
|
|
951
|
+
if (form &&
|
|
952
|
+
submissionDoesNotDismissDialog(form, submitter) &&
|
|
953
|
+
submissionDoesNotTargetIFrame(form, submitter) &&
|
|
954
|
+
this.delegate.willSubmitForm(form, submitter)) {
|
|
796
955
|
event.preventDefault();
|
|
797
956
|
event.stopImmediatePropagation();
|
|
798
|
-
this.delegate.
|
|
957
|
+
this.delegate.formSubmitted(form, submitter);
|
|
799
958
|
}
|
|
800
959
|
}
|
|
801
960
|
});
|
|
802
961
|
this.delegate = delegate;
|
|
803
|
-
this.
|
|
962
|
+
this.eventTarget = eventTarget;
|
|
804
963
|
}
|
|
805
964
|
start() {
|
|
806
|
-
|
|
965
|
+
if (!this.started) {
|
|
966
|
+
this.eventTarget.addEventListener("submit", this.submitCaptured, true);
|
|
967
|
+
this.started = true;
|
|
968
|
+
}
|
|
807
969
|
}
|
|
808
970
|
stop() {
|
|
809
|
-
|
|
971
|
+
if (this.started) {
|
|
972
|
+
this.eventTarget.removeEventListener("submit", this.submitCaptured, true);
|
|
973
|
+
this.started = false;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
function submissionDoesNotDismissDialog(form, submitter) {
|
|
978
|
+
const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.getAttribute("method");
|
|
979
|
+
return method != "dialog";
|
|
980
|
+
}
|
|
981
|
+
function submissionDoesNotTargetIFrame(form, submitter) {
|
|
982
|
+
if ((submitter === null || submitter === void 0 ? void 0 : submitter.hasAttribute("formtarget")) || form.hasAttribute("target")) {
|
|
983
|
+
const target = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formtarget")) || form.target;
|
|
984
|
+
for (const element of document.getElementsByName(target)) {
|
|
985
|
+
if (element instanceof HTMLIFrameElement)
|
|
986
|
+
return false;
|
|
987
|
+
}
|
|
988
|
+
return true;
|
|
989
|
+
}
|
|
990
|
+
else {
|
|
991
|
+
return true;
|
|
810
992
|
}
|
|
811
993
|
}
|
|
812
994
|
|
|
813
995
|
class View {
|
|
814
996
|
constructor(delegate, element) {
|
|
815
|
-
this.resolveRenderPromise = (
|
|
816
|
-
this.resolveInterceptionPromise = (
|
|
997
|
+
this.resolveRenderPromise = (_value) => { };
|
|
998
|
+
this.resolveInterceptionPromise = (_value) => { };
|
|
817
999
|
this.delegate = delegate;
|
|
818
1000
|
this.element = element;
|
|
819
1001
|
}
|
|
@@ -858,15 +1040,17 @@ Copyright © 2021 Basecamp, LLC
|
|
|
858
1040
|
const { isPreview, shouldRender, newSnapshot: snapshot } = renderer;
|
|
859
1041
|
if (shouldRender) {
|
|
860
1042
|
try {
|
|
861
|
-
this.renderPromise = new Promise(resolve => this.resolveRenderPromise = resolve);
|
|
1043
|
+
this.renderPromise = new Promise((resolve) => (this.resolveRenderPromise = resolve));
|
|
862
1044
|
this.renderer = renderer;
|
|
863
|
-
this.prepareToRenderSnapshot(renderer);
|
|
864
|
-
const renderInterception = new Promise(resolve => this.resolveInterceptionPromise = resolve);
|
|
865
|
-
const
|
|
1045
|
+
await this.prepareToRenderSnapshot(renderer);
|
|
1046
|
+
const renderInterception = new Promise((resolve) => (this.resolveInterceptionPromise = resolve));
|
|
1047
|
+
const options = { resume: this.resolveInterceptionPromise, render: this.renderer.renderElement };
|
|
1048
|
+
const immediateRender = this.delegate.allowsImmediateRender(snapshot, options);
|
|
866
1049
|
if (!immediateRender)
|
|
867
1050
|
await renderInterception;
|
|
868
1051
|
await this.renderSnapshot(renderer);
|
|
869
1052
|
this.delegate.viewRenderedSnapshot(snapshot, isPreview);
|
|
1053
|
+
this.delegate.preloadOnLoadLinksForView(this.element);
|
|
870
1054
|
this.finishRenderingSnapshot(renderer);
|
|
871
1055
|
}
|
|
872
1056
|
finally {
|
|
@@ -876,15 +1060,15 @@ Copyright © 2021 Basecamp, LLC
|
|
|
876
1060
|
}
|
|
877
1061
|
}
|
|
878
1062
|
else {
|
|
879
|
-
this.invalidate();
|
|
1063
|
+
this.invalidate(renderer.reloadReason);
|
|
880
1064
|
}
|
|
881
1065
|
}
|
|
882
|
-
invalidate() {
|
|
883
|
-
this.delegate.viewInvalidated();
|
|
1066
|
+
invalidate(reason) {
|
|
1067
|
+
this.delegate.viewInvalidated(reason);
|
|
884
1068
|
}
|
|
885
|
-
prepareToRenderSnapshot(renderer) {
|
|
1069
|
+
async prepareToRenderSnapshot(renderer) {
|
|
886
1070
|
this.markAsPreview(renderer.isPreview);
|
|
887
|
-
renderer.prepareToRender();
|
|
1071
|
+
await renderer.prepareToRender();
|
|
888
1072
|
}
|
|
889
1073
|
markAsPreview(isPreview) {
|
|
890
1074
|
if (isPreview) {
|
|
@@ -903,8 +1087,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
903
1087
|
}
|
|
904
1088
|
|
|
905
1089
|
class FrameView extends View {
|
|
906
|
-
|
|
907
|
-
this.element.innerHTML = ""
|
|
1090
|
+
missing() {
|
|
1091
|
+
this.element.innerHTML = `<strong class="turbo-frame-error">Content missing</strong>`;
|
|
908
1092
|
}
|
|
909
1093
|
get snapshot() {
|
|
910
1094
|
return new Snapshot(this.element);
|
|
@@ -923,17 +1107,17 @@ Copyright © 2021 Basecamp, LLC
|
|
|
923
1107
|
};
|
|
924
1108
|
this.linkClicked = ((event) => {
|
|
925
1109
|
if (this.clickEvent && this.respondsToEventTarget(event.target) && event.target instanceof Element) {
|
|
926
|
-
if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url)) {
|
|
1110
|
+
if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url, event.detail.originalEvent)) {
|
|
927
1111
|
this.clickEvent.preventDefault();
|
|
928
1112
|
event.preventDefault();
|
|
929
|
-
this.delegate.linkClickIntercepted(event.target, event.detail.url);
|
|
1113
|
+
this.delegate.linkClickIntercepted(event.target, event.detail.url, event.detail.originalEvent);
|
|
930
1114
|
}
|
|
931
1115
|
}
|
|
932
1116
|
delete this.clickEvent;
|
|
933
1117
|
});
|
|
934
|
-
this.willVisit = () => {
|
|
1118
|
+
this.willVisit = ((_event) => {
|
|
935
1119
|
delete this.clickEvent;
|
|
936
|
-
};
|
|
1120
|
+
});
|
|
937
1121
|
this.delegate = delegate;
|
|
938
1122
|
this.element = element;
|
|
939
1123
|
}
|
|
@@ -948,28 +1132,137 @@ Copyright © 2021 Basecamp, LLC
|
|
|
948
1132
|
document.removeEventListener("turbo:before-visit", this.willVisit);
|
|
949
1133
|
}
|
|
950
1134
|
respondsToEventTarget(target) {
|
|
951
|
-
const element = target instanceof Element
|
|
952
|
-
? target
|
|
953
|
-
: target instanceof Node
|
|
954
|
-
? target.parentElement
|
|
955
|
-
: null;
|
|
1135
|
+
const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
|
|
956
1136
|
return element && element.closest("turbo-frame, html") == this.element;
|
|
957
1137
|
}
|
|
958
1138
|
}
|
|
959
1139
|
|
|
960
|
-
class
|
|
961
|
-
constructor(
|
|
962
|
-
this.
|
|
1140
|
+
class LinkClickObserver {
|
|
1141
|
+
constructor(delegate, eventTarget) {
|
|
1142
|
+
this.started = false;
|
|
1143
|
+
this.clickCaptured = () => {
|
|
1144
|
+
this.eventTarget.removeEventListener("click", this.clickBubbled, false);
|
|
1145
|
+
this.eventTarget.addEventListener("click", this.clickBubbled, false);
|
|
1146
|
+
};
|
|
1147
|
+
this.clickBubbled = (event) => {
|
|
1148
|
+
if (event instanceof MouseEvent && this.clickEventIsSignificant(event)) {
|
|
1149
|
+
const target = (event.composedPath && event.composedPath()[0]) || event.target;
|
|
1150
|
+
const link = this.findLinkFromClickTarget(target);
|
|
1151
|
+
if (link && doesNotTargetIFrame(link)) {
|
|
1152
|
+
const location = this.getLocationForLink(link);
|
|
1153
|
+
if (this.delegate.willFollowLinkToLocation(link, location, event)) {
|
|
1154
|
+
event.preventDefault();
|
|
1155
|
+
this.delegate.followedLinkToLocation(link, location);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
this.delegate = delegate;
|
|
1161
|
+
this.eventTarget = eventTarget;
|
|
1162
|
+
}
|
|
1163
|
+
start() {
|
|
1164
|
+
if (!this.started) {
|
|
1165
|
+
this.eventTarget.addEventListener("click", this.clickCaptured, true);
|
|
1166
|
+
this.started = true;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
stop() {
|
|
1170
|
+
if (this.started) {
|
|
1171
|
+
this.eventTarget.removeEventListener("click", this.clickCaptured, true);
|
|
1172
|
+
this.started = false;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
clickEventIsSignificant(event) {
|
|
1176
|
+
return !((event.target && event.target.isContentEditable) ||
|
|
1177
|
+
event.defaultPrevented ||
|
|
1178
|
+
event.which > 1 ||
|
|
1179
|
+
event.altKey ||
|
|
1180
|
+
event.ctrlKey ||
|
|
1181
|
+
event.metaKey ||
|
|
1182
|
+
event.shiftKey);
|
|
1183
|
+
}
|
|
1184
|
+
findLinkFromClickTarget(target) {
|
|
1185
|
+
return findClosestRecursively(target, "a[href]:not([target^=_]):not([download])");
|
|
1186
|
+
}
|
|
1187
|
+
getLocationForLink(link) {
|
|
1188
|
+
return expandURL(link.getAttribute("href") || "");
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
function doesNotTargetIFrame(anchor) {
|
|
1192
|
+
if (anchor.hasAttribute("target")) {
|
|
1193
|
+
for (const element of document.getElementsByName(anchor.target)) {
|
|
1194
|
+
if (element instanceof HTMLIFrameElement)
|
|
1195
|
+
return false;
|
|
1196
|
+
}
|
|
1197
|
+
return true;
|
|
1198
|
+
}
|
|
1199
|
+
else {
|
|
1200
|
+
return true;
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
class FormLinkClickObserver {
|
|
1205
|
+
constructor(delegate, element) {
|
|
1206
|
+
this.delegate = delegate;
|
|
1207
|
+
this.linkInterceptor = new LinkClickObserver(this, element);
|
|
963
1208
|
}
|
|
964
|
-
|
|
965
|
-
|
|
1209
|
+
start() {
|
|
1210
|
+
this.linkInterceptor.start();
|
|
1211
|
+
}
|
|
1212
|
+
stop() {
|
|
1213
|
+
this.linkInterceptor.stop();
|
|
1214
|
+
}
|
|
1215
|
+
willFollowLinkToLocation(link, location, originalEvent) {
|
|
1216
|
+
return (this.delegate.willSubmitFormLinkToLocation(link, location, originalEvent) &&
|
|
1217
|
+
link.hasAttribute("data-turbo-method"));
|
|
1218
|
+
}
|
|
1219
|
+
followedLinkToLocation(link, location) {
|
|
1220
|
+
const form = document.createElement("form");
|
|
1221
|
+
const type = "hidden";
|
|
1222
|
+
for (const [name, value] of location.searchParams) {
|
|
1223
|
+
form.append(Object.assign(document.createElement("input"), { type, name, value }));
|
|
1224
|
+
}
|
|
1225
|
+
const action = Object.assign(location, { search: "" });
|
|
1226
|
+
form.setAttribute("data-turbo", "true");
|
|
1227
|
+
form.setAttribute("action", action.href);
|
|
1228
|
+
form.setAttribute("hidden", "");
|
|
1229
|
+
const method = link.getAttribute("data-turbo-method");
|
|
1230
|
+
if (method)
|
|
1231
|
+
form.setAttribute("method", method);
|
|
1232
|
+
const turboFrame = link.getAttribute("data-turbo-frame");
|
|
1233
|
+
if (turboFrame)
|
|
1234
|
+
form.setAttribute("data-turbo-frame", turboFrame);
|
|
1235
|
+
const turboAction = getVisitAction(link);
|
|
1236
|
+
if (turboAction)
|
|
1237
|
+
form.setAttribute("data-turbo-action", turboAction);
|
|
1238
|
+
const turboConfirm = link.getAttribute("data-turbo-confirm");
|
|
1239
|
+
if (turboConfirm)
|
|
1240
|
+
form.setAttribute("data-turbo-confirm", turboConfirm);
|
|
1241
|
+
const turboStream = link.hasAttribute("data-turbo-stream");
|
|
1242
|
+
if (turboStream)
|
|
1243
|
+
form.setAttribute("data-turbo-stream", "");
|
|
1244
|
+
this.delegate.submittedFormLinkToLocation(link, location, form);
|
|
1245
|
+
document.body.appendChild(form);
|
|
1246
|
+
form.addEventListener("turbo:submit-end", () => form.remove(), { once: true });
|
|
1247
|
+
requestAnimationFrame(() => form.requestSubmit());
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
class Bardo {
|
|
1252
|
+
static async preservingPermanentElements(delegate, permanentElementMap, callback) {
|
|
1253
|
+
const bardo = new this(delegate, permanentElementMap);
|
|
966
1254
|
bardo.enter();
|
|
967
|
-
callback();
|
|
1255
|
+
await callback();
|
|
968
1256
|
bardo.leave();
|
|
969
1257
|
}
|
|
1258
|
+
constructor(delegate, permanentElementMap) {
|
|
1259
|
+
this.delegate = delegate;
|
|
1260
|
+
this.permanentElementMap = permanentElementMap;
|
|
1261
|
+
}
|
|
970
1262
|
enter() {
|
|
971
1263
|
for (const id in this.permanentElementMap) {
|
|
972
|
-
const [, newPermanentElement] = this.permanentElementMap[id];
|
|
1264
|
+
const [currentPermanentElement, newPermanentElement] = this.permanentElementMap[id];
|
|
1265
|
+
this.delegate.enteringBardo(currentPermanentElement, newPermanentElement);
|
|
973
1266
|
this.replaceNewPermanentElementWithPlaceholder(newPermanentElement);
|
|
974
1267
|
}
|
|
975
1268
|
}
|
|
@@ -978,6 +1271,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
978
1271
|
const [currentPermanentElement] = this.permanentElementMap[id];
|
|
979
1272
|
this.replaceCurrentPermanentElementWithClone(currentPermanentElement);
|
|
980
1273
|
this.replacePlaceholderWithPermanentElement(currentPermanentElement);
|
|
1274
|
+
this.delegate.leavingBardo(currentPermanentElement);
|
|
981
1275
|
}
|
|
982
1276
|
}
|
|
983
1277
|
replaceNewPermanentElementWithPlaceholder(permanentElement) {
|
|
@@ -993,7 +1287,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
993
1287
|
placeholder === null || placeholder === void 0 ? void 0 : placeholder.replaceWith(permanentElement);
|
|
994
1288
|
}
|
|
995
1289
|
getPlaceholderById(id) {
|
|
996
|
-
return this.placeholders.find(element => element.content == id);
|
|
1290
|
+
return this.placeholders.find((element) => element.content == id);
|
|
997
1291
|
}
|
|
998
1292
|
get placeholders() {
|
|
999
1293
|
return [...document.querySelectorAll("meta[name=turbo-permanent-placeholder][content]")];
|
|
@@ -1007,16 +1301,21 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1007
1301
|
}
|
|
1008
1302
|
|
|
1009
1303
|
class Renderer {
|
|
1010
|
-
constructor(currentSnapshot, newSnapshot, isPreview, willRender = true) {
|
|
1304
|
+
constructor(currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
|
|
1305
|
+
this.activeElement = null;
|
|
1011
1306
|
this.currentSnapshot = currentSnapshot;
|
|
1012
1307
|
this.newSnapshot = newSnapshot;
|
|
1013
1308
|
this.isPreview = isPreview;
|
|
1014
1309
|
this.willRender = willRender;
|
|
1015
|
-
this.
|
|
1310
|
+
this.renderElement = renderElement;
|
|
1311
|
+
this.promise = new Promise((resolve, reject) => (this.resolvingFunctions = { resolve, reject }));
|
|
1016
1312
|
}
|
|
1017
1313
|
get shouldRender() {
|
|
1018
1314
|
return true;
|
|
1019
1315
|
}
|
|
1316
|
+
get reloadReason() {
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1020
1319
|
prepareToRender() {
|
|
1021
1320
|
return;
|
|
1022
1321
|
}
|
|
@@ -1026,23 +1325,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1026
1325
|
delete this.resolvingFunctions;
|
|
1027
1326
|
}
|
|
1028
1327
|
}
|
|
1029
|
-
|
|
1030
|
-
|
|
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
|
-
preservingPermanentElements(callback) {
|
|
1045
|
-
Bardo.preservingPermanentElements(this.permanentElementMap, callback);
|
|
1328
|
+
async preservingPermanentElements(callback) {
|
|
1329
|
+
await Bardo.preservingPermanentElements(this, this.permanentElementMap, callback);
|
|
1046
1330
|
}
|
|
1047
1331
|
focusFirstAutofocusableElement() {
|
|
1048
1332
|
const element = this.connectedSnapshot.firstAutofocusableElement;
|
|
@@ -1050,6 +1334,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1050
1334
|
element.focus();
|
|
1051
1335
|
}
|
|
1052
1336
|
}
|
|
1337
|
+
enteringBardo(currentPermanentElement) {
|
|
1338
|
+
if (this.activeElement)
|
|
1339
|
+
return;
|
|
1340
|
+
if (currentPermanentElement.contains(this.currentSnapshot.activeElement)) {
|
|
1341
|
+
this.activeElement = this.currentSnapshot.activeElement;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
leavingBardo(currentPermanentElement) {
|
|
1345
|
+
if (currentPermanentElement.contains(this.activeElement) && this.activeElement instanceof HTMLElement) {
|
|
1346
|
+
this.activeElement.focus();
|
|
1347
|
+
this.activeElement = null;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1053
1350
|
get connectedSnapshot() {
|
|
1054
1351
|
return this.newSnapshot.isConnected ? this.newSnapshot : this.currentSnapshot;
|
|
1055
1352
|
}
|
|
@@ -1062,21 +1359,28 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1062
1359
|
get permanentElementMap() {
|
|
1063
1360
|
return this.currentSnapshot.getPermanentElementMapForSnapshot(this.newSnapshot);
|
|
1064
1361
|
}
|
|
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
1362
|
}
|
|
1075
1363
|
function elementIsFocusable(element) {
|
|
1076
1364
|
return element && typeof element.focus == "function";
|
|
1077
1365
|
}
|
|
1078
1366
|
|
|
1079
1367
|
class FrameRenderer extends Renderer {
|
|
1368
|
+
static renderElement(currentElement, newElement) {
|
|
1369
|
+
var _a;
|
|
1370
|
+
const destinationRange = document.createRange();
|
|
1371
|
+
destinationRange.selectNodeContents(currentElement);
|
|
1372
|
+
destinationRange.deleteContents();
|
|
1373
|
+
const frameElement = newElement;
|
|
1374
|
+
const sourceRange = (_a = frameElement.ownerDocument) === null || _a === void 0 ? void 0 : _a.createRange();
|
|
1375
|
+
if (sourceRange) {
|
|
1376
|
+
sourceRange.selectNodeContents(frameElement);
|
|
1377
|
+
currentElement.appendChild(sourceRange.extractContents());
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
constructor(delegate, currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
|
|
1381
|
+
super(currentSnapshot, newSnapshot, renderElement, isPreview, willRender);
|
|
1382
|
+
this.delegate = delegate;
|
|
1383
|
+
}
|
|
1080
1384
|
get shouldRender() {
|
|
1081
1385
|
return true;
|
|
1082
1386
|
}
|
|
@@ -1092,23 +1396,16 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1092
1396
|
this.activateScriptElements();
|
|
1093
1397
|
}
|
|
1094
1398
|
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
|
-
}
|
|
1399
|
+
this.delegate.willRenderFrame(this.currentElement, this.newElement);
|
|
1400
|
+
this.renderElement(this.currentElement, this.newElement);
|
|
1105
1401
|
}
|
|
1106
1402
|
scrollFrameIntoView() {
|
|
1107
1403
|
if (this.currentElement.autoscroll || this.newElement.autoscroll) {
|
|
1108
1404
|
const element = this.currentElement.firstElementChild;
|
|
1109
1405
|
const block = readScrollLogicalPosition(this.currentElement.getAttribute("data-autoscroll-block"), "end");
|
|
1406
|
+
const behavior = readScrollBehavior(this.currentElement.getAttribute("data-autoscroll-behavior"), "auto");
|
|
1110
1407
|
if (element) {
|
|
1111
|
-
element.scrollIntoView({ block });
|
|
1408
|
+
element.scrollIntoView({ block, behavior });
|
|
1112
1409
|
return true;
|
|
1113
1410
|
}
|
|
1114
1411
|
}
|
|
@@ -1116,7 +1413,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1116
1413
|
}
|
|
1117
1414
|
activateScriptElements() {
|
|
1118
1415
|
for (const inertScriptElement of this.newScriptElements) {
|
|
1119
|
-
const activatedScriptElement =
|
|
1416
|
+
const activatedScriptElement = activateScriptElement(inertScriptElement);
|
|
1120
1417
|
inertScriptElement.replaceWith(activatedScriptElement);
|
|
1121
1418
|
}
|
|
1122
1419
|
}
|
|
@@ -1132,20 +1429,16 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1132
1429
|
return defaultValue;
|
|
1133
1430
|
}
|
|
1134
1431
|
}
|
|
1432
|
+
function readScrollBehavior(value, defaultValue) {
|
|
1433
|
+
if (value == "auto" || value == "smooth") {
|
|
1434
|
+
return value;
|
|
1435
|
+
}
|
|
1436
|
+
else {
|
|
1437
|
+
return defaultValue;
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1135
1440
|
|
|
1136
1441
|
class ProgressBar {
|
|
1137
|
-
constructor() {
|
|
1138
|
-
this.hiding = false;
|
|
1139
|
-
this.value = 0;
|
|
1140
|
-
this.visible = false;
|
|
1141
|
-
this.trickle = () => {
|
|
1142
|
-
this.setValue(this.value + Math.random() / 100);
|
|
1143
|
-
};
|
|
1144
|
-
this.stylesheetElement = this.createStylesheetElement();
|
|
1145
|
-
this.progressElement = this.createProgressElement();
|
|
1146
|
-
this.installStylesheetElement();
|
|
1147
|
-
this.setValue(0);
|
|
1148
|
-
}
|
|
1149
1442
|
static get defaultCSS() {
|
|
1150
1443
|
return unindent `
|
|
1151
1444
|
.turbo-progress-bar {
|
|
@@ -1155,7 +1448,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1155
1448
|
left: 0;
|
|
1156
1449
|
height: 3px;
|
|
1157
1450
|
background: #0076ff;
|
|
1158
|
-
z-index:
|
|
1451
|
+
z-index: 2147483647;
|
|
1159
1452
|
transition:
|
|
1160
1453
|
width ${ProgressBar.animationDuration}ms ease-out,
|
|
1161
1454
|
opacity ${ProgressBar.animationDuration / 2}ms ${ProgressBar.animationDuration / 2}ms ease-in;
|
|
@@ -1163,6 +1456,18 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1163
1456
|
}
|
|
1164
1457
|
`;
|
|
1165
1458
|
}
|
|
1459
|
+
constructor() {
|
|
1460
|
+
this.hiding = false;
|
|
1461
|
+
this.value = 0;
|
|
1462
|
+
this.visible = false;
|
|
1463
|
+
this.trickle = () => {
|
|
1464
|
+
this.setValue(this.value + Math.random() / 100);
|
|
1465
|
+
};
|
|
1466
|
+
this.stylesheetElement = this.createStylesheetElement();
|
|
1467
|
+
this.progressElement = this.createProgressElement();
|
|
1468
|
+
this.installStylesheetElement();
|
|
1469
|
+
this.setValue(0);
|
|
1470
|
+
}
|
|
1166
1471
|
show() {
|
|
1167
1472
|
if (!this.visible) {
|
|
1168
1473
|
this.visible = true;
|
|
@@ -1214,13 +1519,16 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1214
1519
|
}
|
|
1215
1520
|
refresh() {
|
|
1216
1521
|
requestAnimationFrame(() => {
|
|
1217
|
-
this.progressElement.style.width = `${10 +
|
|
1522
|
+
this.progressElement.style.width = `${10 + this.value * 90}%`;
|
|
1218
1523
|
});
|
|
1219
1524
|
}
|
|
1220
1525
|
createStylesheetElement() {
|
|
1221
1526
|
const element = document.createElement("style");
|
|
1222
1527
|
element.type = "text/css";
|
|
1223
1528
|
element.textContent = ProgressBar.defaultCSS;
|
|
1529
|
+
if (this.cspNonce) {
|
|
1530
|
+
element.nonce = this.cspNonce;
|
|
1531
|
+
}
|
|
1224
1532
|
return element;
|
|
1225
1533
|
}
|
|
1226
1534
|
createProgressElement() {
|
|
@@ -1228,6 +1536,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1228
1536
|
element.className = "turbo-progress-bar";
|
|
1229
1537
|
return element;
|
|
1230
1538
|
}
|
|
1539
|
+
get cspNonce() {
|
|
1540
|
+
return getMetaContent("csp-nonce");
|
|
1541
|
+
}
|
|
1231
1542
|
}
|
|
1232
1543
|
ProgressBar.animationDuration = 300;
|
|
1233
1544
|
|
|
@@ -1244,14 +1555,14 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1244
1555
|
: {
|
|
1245
1556
|
type: elementType(element),
|
|
1246
1557
|
tracked: elementIsTracked(element),
|
|
1247
|
-
elements: []
|
|
1558
|
+
elements: [],
|
|
1248
1559
|
};
|
|
1249
1560
|
return Object.assign(Object.assign({}, result), { [outerHTML]: Object.assign(Object.assign({}, details), { elements: [...details.elements, element] }) });
|
|
1250
1561
|
}, {});
|
|
1251
1562
|
}
|
|
1252
1563
|
get trackedElementSignature() {
|
|
1253
1564
|
return Object.keys(this.detailsByOuterHTML)
|
|
1254
|
-
.filter(outerHTML => this.detailsByOuterHTML[outerHTML].tracked)
|
|
1565
|
+
.filter((outerHTML) => this.detailsByOuterHTML[outerHTML].tracked)
|
|
1255
1566
|
.join("");
|
|
1256
1567
|
}
|
|
1257
1568
|
getScriptElementsNotInSnapshot(snapshot) {
|
|
@@ -1262,8 +1573,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1262
1573
|
}
|
|
1263
1574
|
getElementsMatchingTypeNotInSnapshot(matchedType, snapshot) {
|
|
1264
1575
|
return Object.keys(this.detailsByOuterHTML)
|
|
1265
|
-
.filter(outerHTML => !(outerHTML in snapshot.detailsByOuterHTML))
|
|
1266
|
-
.map(outerHTML => this.detailsByOuterHTML[outerHTML])
|
|
1576
|
+
.filter((outerHTML) => !(outerHTML in snapshot.detailsByOuterHTML))
|
|
1577
|
+
.map((outerHTML) => this.detailsByOuterHTML[outerHTML])
|
|
1267
1578
|
.filter(({ type }) => type == matchedType)
|
|
1268
1579
|
.map(({ elements: [element] }) => element);
|
|
1269
1580
|
}
|
|
@@ -1283,13 +1594,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1283
1594
|
}
|
|
1284
1595
|
getMetaValue(name) {
|
|
1285
1596
|
const element = this.findMetaElementByName(name);
|
|
1286
|
-
return element
|
|
1287
|
-
? element.getAttribute("content")
|
|
1288
|
-
: null;
|
|
1597
|
+
return element ? element.getAttribute("content") : null;
|
|
1289
1598
|
}
|
|
1290
1599
|
findMetaElementByName(name) {
|
|
1291
1600
|
return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => {
|
|
1292
|
-
const { elements: [element] } = this.detailsByOuterHTML[outerHTML];
|
|
1601
|
+
const { elements: [element], } = this.detailsByOuterHTML[outerHTML];
|
|
1293
1602
|
return elementIsMetaElementWithName(element, name) ? element : result;
|
|
1294
1603
|
}, undefined);
|
|
1295
1604
|
}
|
|
@@ -1306,19 +1615,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1306
1615
|
return element.getAttribute("data-turbo-track") == "reload";
|
|
1307
1616
|
}
|
|
1308
1617
|
function elementIsScript(element) {
|
|
1309
|
-
const tagName = element.
|
|
1618
|
+
const tagName = element.localName;
|
|
1310
1619
|
return tagName == "script";
|
|
1311
1620
|
}
|
|
1312
1621
|
function elementIsNoscript(element) {
|
|
1313
|
-
const tagName = element.
|
|
1622
|
+
const tagName = element.localName;
|
|
1314
1623
|
return tagName == "noscript";
|
|
1315
1624
|
}
|
|
1316
1625
|
function elementIsStylesheet(element) {
|
|
1317
|
-
const tagName = element.
|
|
1626
|
+
const tagName = element.localName;
|
|
1318
1627
|
return tagName == "style" || (tagName == "link" && element.getAttribute("rel") == "stylesheet");
|
|
1319
1628
|
}
|
|
1320
1629
|
function elementIsMetaElementWithName(element, name) {
|
|
1321
|
-
const tagName = element.
|
|
1630
|
+
const tagName = element.localName;
|
|
1322
1631
|
return tagName == "meta" && element.getAttribute("name") == name;
|
|
1323
1632
|
}
|
|
1324
1633
|
function elementWithoutNonce(element) {
|
|
@@ -1329,10 +1638,6 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1329
1638
|
}
|
|
1330
1639
|
|
|
1331
1640
|
class PageSnapshot extends Snapshot {
|
|
1332
|
-
constructor(element, headSnapshot) {
|
|
1333
|
-
super(element);
|
|
1334
|
-
this.headSnapshot = headSnapshot;
|
|
1335
|
-
}
|
|
1336
1641
|
static fromHTMLString(html = "") {
|
|
1337
1642
|
return this.fromDocument(parseHTMLDocument(html));
|
|
1338
1643
|
}
|
|
@@ -1342,8 +1647,25 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1342
1647
|
static fromDocument({ head, body }) {
|
|
1343
1648
|
return new this(body, new HeadSnapshot(head));
|
|
1344
1649
|
}
|
|
1650
|
+
constructor(element, headSnapshot) {
|
|
1651
|
+
super(element);
|
|
1652
|
+
this.headSnapshot = headSnapshot;
|
|
1653
|
+
}
|
|
1345
1654
|
clone() {
|
|
1346
|
-
|
|
1655
|
+
const clonedElement = this.element.cloneNode(true);
|
|
1656
|
+
const selectElements = this.element.querySelectorAll("select");
|
|
1657
|
+
const clonedSelectElements = clonedElement.querySelectorAll("select");
|
|
1658
|
+
for (const [index, source] of selectElements.entries()) {
|
|
1659
|
+
const clone = clonedSelectElements[index];
|
|
1660
|
+
for (const option of clone.selectedOptions)
|
|
1661
|
+
option.selected = false;
|
|
1662
|
+
for (const option of source.selectedOptions)
|
|
1663
|
+
clone.options[option.index].selected = true;
|
|
1664
|
+
}
|
|
1665
|
+
for (const clonedPasswordInput of clonedElement.querySelectorAll('input[type="password"]')) {
|
|
1666
|
+
clonedPasswordInput.value = "";
|
|
1667
|
+
}
|
|
1668
|
+
return new PageSnapshot(clonedElement, this.headSnapshot);
|
|
1347
1669
|
}
|
|
1348
1670
|
get headElement() {
|
|
1349
1671
|
return this.headSnapshot.element;
|
|
@@ -1390,6 +1712,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1390
1712
|
historyChanged: false,
|
|
1391
1713
|
visitCachedSnapshot: () => { },
|
|
1392
1714
|
willRender: true,
|
|
1715
|
+
updateHistory: true,
|
|
1716
|
+
shouldCacheSnapshot: true,
|
|
1717
|
+
acceptsStreamResponse: false,
|
|
1393
1718
|
};
|
|
1394
1719
|
var SystemStatusCode;
|
|
1395
1720
|
(function (SystemStatusCode) {
|
|
@@ -1404,21 +1729,27 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1404
1729
|
this.followedRedirect = false;
|
|
1405
1730
|
this.historyChanged = false;
|
|
1406
1731
|
this.scrolled = false;
|
|
1732
|
+
this.shouldCacheSnapshot = true;
|
|
1733
|
+
this.acceptsStreamResponse = false;
|
|
1407
1734
|
this.snapshotCached = false;
|
|
1408
1735
|
this.state = VisitState.initialized;
|
|
1409
1736
|
this.delegate = delegate;
|
|
1410
1737
|
this.location = location;
|
|
1411
1738
|
this.restorationIdentifier = restorationIdentifier || uuid();
|
|
1412
|
-
const { action, historyChanged, referrer, snapshotHTML, response, visitCachedSnapshot, willRender } = Object.assign(Object.assign({}, defaultOptions), options);
|
|
1739
|
+
const { action, historyChanged, referrer, snapshot, snapshotHTML, response, visitCachedSnapshot, willRender, updateHistory, shouldCacheSnapshot, acceptsStreamResponse, } = Object.assign(Object.assign({}, defaultOptions), options);
|
|
1413
1740
|
this.action = action;
|
|
1414
1741
|
this.historyChanged = historyChanged;
|
|
1415
1742
|
this.referrer = referrer;
|
|
1743
|
+
this.snapshot = snapshot;
|
|
1416
1744
|
this.snapshotHTML = snapshotHTML;
|
|
1417
1745
|
this.response = response;
|
|
1418
1746
|
this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action);
|
|
1419
1747
|
this.visitCachedSnapshot = visitCachedSnapshot;
|
|
1420
1748
|
this.willRender = willRender;
|
|
1749
|
+
this.updateHistory = updateHistory;
|
|
1421
1750
|
this.scrolled = !willRender;
|
|
1751
|
+
this.shouldCacheSnapshot = shouldCacheSnapshot;
|
|
1752
|
+
this.acceptsStreamResponse = acceptsStreamResponse;
|
|
1422
1753
|
}
|
|
1423
1754
|
get adapter() {
|
|
1424
1755
|
return this.delegate.adapter;
|
|
@@ -1456,9 +1787,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1456
1787
|
if (this.state == VisitState.started) {
|
|
1457
1788
|
this.recordTimingMetric(TimingMetric.visitEnd);
|
|
1458
1789
|
this.state = VisitState.completed;
|
|
1459
|
-
this.adapter.visitCompleted(this);
|
|
1460
|
-
this.delegate.visitCompleted(this);
|
|
1461
1790
|
this.followRedirect();
|
|
1791
|
+
if (!this.followedRedirect) {
|
|
1792
|
+
this.adapter.visitCompleted(this);
|
|
1793
|
+
this.delegate.visitCompleted(this);
|
|
1794
|
+
}
|
|
1462
1795
|
}
|
|
1463
1796
|
}
|
|
1464
1797
|
fail() {
|
|
@@ -1469,9 +1802,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1469
1802
|
}
|
|
1470
1803
|
changeHistory() {
|
|
1471
1804
|
var _a;
|
|
1472
|
-
if (!this.historyChanged) {
|
|
1805
|
+
if (!this.historyChanged && this.updateHistory) {
|
|
1473
1806
|
const actionForHistory = this.location.href === ((_a = this.referrer) === null || _a === void 0 ? void 0 : _a.href) ? "replace" : this.action;
|
|
1474
|
-
const method =
|
|
1807
|
+
const method = getHistoryMethodForAction(actionForHistory);
|
|
1475
1808
|
this.history.update(method, this.location, this.restorationIdentifier);
|
|
1476
1809
|
this.historyChanged = true;
|
|
1477
1810
|
}
|
|
@@ -1516,16 +1849,18 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1516
1849
|
if (this.response) {
|
|
1517
1850
|
const { statusCode, responseHTML } = this.response;
|
|
1518
1851
|
this.render(async () => {
|
|
1519
|
-
this.
|
|
1852
|
+
if (this.shouldCacheSnapshot)
|
|
1853
|
+
this.cacheSnapshot();
|
|
1520
1854
|
if (this.view.renderPromise)
|
|
1521
1855
|
await this.view.renderPromise;
|
|
1522
1856
|
if (isSuccessful(statusCode) && responseHTML != null) {
|
|
1523
|
-
await this.view.renderPage(PageSnapshot.fromHTMLString(responseHTML), false, this.willRender);
|
|
1857
|
+
await this.view.renderPage(PageSnapshot.fromHTMLString(responseHTML), false, this.willRender, this);
|
|
1858
|
+
this.performScroll();
|
|
1524
1859
|
this.adapter.visitRendered(this);
|
|
1525
1860
|
this.complete();
|
|
1526
1861
|
}
|
|
1527
1862
|
else {
|
|
1528
|
-
await this.view.renderError(PageSnapshot.fromHTMLString(responseHTML));
|
|
1863
|
+
await this.view.renderError(PageSnapshot.fromHTMLString(responseHTML), this);
|
|
1529
1864
|
this.adapter.visitRendered(this);
|
|
1530
1865
|
this.fail();
|
|
1531
1866
|
}
|
|
@@ -1560,7 +1895,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1560
1895
|
else {
|
|
1561
1896
|
if (this.view.renderPromise)
|
|
1562
1897
|
await this.view.renderPromise;
|
|
1563
|
-
await this.view.renderPage(snapshot, isPreview, this.willRender);
|
|
1898
|
+
await this.view.renderPage(snapshot, isPreview, this.willRender, this);
|
|
1899
|
+
this.performScroll();
|
|
1564
1900
|
this.adapter.visitRendered(this);
|
|
1565
1901
|
if (!isPreview) {
|
|
1566
1902
|
this.complete();
|
|
@@ -1573,8 +1909,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1573
1909
|
var _a;
|
|
1574
1910
|
if (this.redirectedToLocation && !this.followedRedirect && ((_a = this.response) === null || _a === void 0 ? void 0 : _a.redirected)) {
|
|
1575
1911
|
this.adapter.visitProposedToLocation(this.redirectedToLocation, {
|
|
1576
|
-
action:
|
|
1577
|
-
response: this.response
|
|
1912
|
+
action: "replace",
|
|
1913
|
+
response: this.response,
|
|
1914
|
+
shouldCacheSnapshot: false,
|
|
1915
|
+
willRender: false,
|
|
1578
1916
|
});
|
|
1579
1917
|
this.followedRedirect = true;
|
|
1580
1918
|
}
|
|
@@ -1583,20 +1921,29 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1583
1921
|
if (this.isSamePage) {
|
|
1584
1922
|
this.render(async () => {
|
|
1585
1923
|
this.cacheSnapshot();
|
|
1924
|
+
this.performScroll();
|
|
1925
|
+
this.changeHistory();
|
|
1586
1926
|
this.adapter.visitRendered(this);
|
|
1587
1927
|
});
|
|
1588
1928
|
}
|
|
1589
1929
|
}
|
|
1930
|
+
prepareRequest(request) {
|
|
1931
|
+
if (this.acceptsStreamResponse) {
|
|
1932
|
+
request.acceptResponseType(StreamMessage.contentType);
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1590
1935
|
requestStarted() {
|
|
1591
1936
|
this.startRequest();
|
|
1592
1937
|
}
|
|
1593
|
-
requestPreventedHandlingResponse(
|
|
1594
|
-
}
|
|
1938
|
+
requestPreventedHandlingResponse(_request, _response) { }
|
|
1595
1939
|
async requestSucceededWithResponse(request, response) {
|
|
1596
1940
|
const responseHTML = await response.responseHTML;
|
|
1597
1941
|
const { redirected, statusCode } = response;
|
|
1598
1942
|
if (responseHTML == undefined) {
|
|
1599
|
-
this.recordResponse({
|
|
1943
|
+
this.recordResponse({
|
|
1944
|
+
statusCode: SystemStatusCode.contentTypeMismatch,
|
|
1945
|
+
redirected,
|
|
1946
|
+
});
|
|
1600
1947
|
}
|
|
1601
1948
|
else {
|
|
1602
1949
|
this.redirectedToLocation = response.redirected ? response.location : undefined;
|
|
@@ -1607,20 +1954,26 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1607
1954
|
const responseHTML = await response.responseHTML;
|
|
1608
1955
|
const { redirected, statusCode } = response;
|
|
1609
1956
|
if (responseHTML == undefined) {
|
|
1610
|
-
this.recordResponse({
|
|
1957
|
+
this.recordResponse({
|
|
1958
|
+
statusCode: SystemStatusCode.contentTypeMismatch,
|
|
1959
|
+
redirected,
|
|
1960
|
+
});
|
|
1611
1961
|
}
|
|
1612
1962
|
else {
|
|
1613
1963
|
this.recordResponse({ statusCode: statusCode, responseHTML, redirected });
|
|
1614
1964
|
}
|
|
1615
1965
|
}
|
|
1616
|
-
requestErrored(
|
|
1617
|
-
this.recordResponse({
|
|
1966
|
+
requestErrored(_request, _error) {
|
|
1967
|
+
this.recordResponse({
|
|
1968
|
+
statusCode: SystemStatusCode.networkFailure,
|
|
1969
|
+
redirected: false,
|
|
1970
|
+
});
|
|
1618
1971
|
}
|
|
1619
1972
|
requestFinished() {
|
|
1620
1973
|
this.finishRequest();
|
|
1621
1974
|
}
|
|
1622
1975
|
performScroll() {
|
|
1623
|
-
if (!this.scrolled) {
|
|
1976
|
+
if (!this.scrolled && !this.view.forceReloaded) {
|
|
1624
1977
|
if (this.action == "restore") {
|
|
1625
1978
|
this.scrollToRestoredPosition() || this.scrollToAnchor() || this.view.scrollToTop();
|
|
1626
1979
|
}
|
|
@@ -1655,9 +2008,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1655
2008
|
}
|
|
1656
2009
|
getHistoryMethodForAction(action) {
|
|
1657
2010
|
switch (action) {
|
|
1658
|
-
case "replace":
|
|
2011
|
+
case "replace":
|
|
2012
|
+
return history.replaceState;
|
|
1659
2013
|
case "advance":
|
|
1660
|
-
case "restore":
|
|
2014
|
+
case "restore":
|
|
2015
|
+
return history.pushState;
|
|
1661
2016
|
}
|
|
1662
2017
|
}
|
|
1663
2018
|
hasPreloadedResponse() {
|
|
@@ -1676,18 +2031,17 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1676
2031
|
}
|
|
1677
2032
|
cacheSnapshot() {
|
|
1678
2033
|
if (!this.snapshotCached) {
|
|
1679
|
-
this.view.cacheSnapshot().then(snapshot => snapshot && this.visitCachedSnapshot(snapshot));
|
|
2034
|
+
this.view.cacheSnapshot(this.snapshot).then((snapshot) => snapshot && this.visitCachedSnapshot(snapshot));
|
|
1680
2035
|
this.snapshotCached = true;
|
|
1681
2036
|
}
|
|
1682
2037
|
}
|
|
1683
2038
|
async render(callback) {
|
|
1684
2039
|
this.cancelRender();
|
|
1685
|
-
await new Promise(resolve => {
|
|
2040
|
+
await new Promise((resolve) => {
|
|
1686
2041
|
this.frame = requestAnimationFrame(() => resolve());
|
|
1687
2042
|
});
|
|
1688
2043
|
await callback();
|
|
1689
2044
|
delete this.frame;
|
|
1690
|
-
this.performScroll();
|
|
1691
2045
|
}
|
|
1692
2046
|
cancelRender() {
|
|
1693
2047
|
if (this.frame) {
|
|
@@ -1702,19 +2056,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1702
2056
|
|
|
1703
2057
|
class BrowserAdapter {
|
|
1704
2058
|
constructor(session) {
|
|
1705
|
-
this.progressBar = new ProgressBar;
|
|
2059
|
+
this.progressBar = new ProgressBar();
|
|
1706
2060
|
this.showProgressBar = () => {
|
|
1707
2061
|
this.progressBar.show();
|
|
1708
2062
|
};
|
|
1709
2063
|
this.session = session;
|
|
1710
2064
|
}
|
|
1711
2065
|
visitProposedToLocation(location, options) {
|
|
1712
|
-
this.navigator.startVisit(location, uuid(), options);
|
|
2066
|
+
this.navigator.startVisit(location, (options === null || options === void 0 ? void 0 : options.restorationIdentifier) || uuid(), options);
|
|
1713
2067
|
}
|
|
1714
2068
|
visitStarted(visit) {
|
|
2069
|
+
this.location = visit.location;
|
|
1715
2070
|
visit.loadCachedSnapshot();
|
|
1716
2071
|
visit.issueRequest();
|
|
1717
|
-
visit.changeHistory();
|
|
1718
2072
|
visit.goToSamePageAnchor();
|
|
1719
2073
|
}
|
|
1720
2074
|
visitRequestStarted(visit) {
|
|
@@ -1734,29 +2088,31 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1734
2088
|
case SystemStatusCode.networkFailure:
|
|
1735
2089
|
case SystemStatusCode.timeoutFailure:
|
|
1736
2090
|
case SystemStatusCode.contentTypeMismatch:
|
|
1737
|
-
return this.reload(
|
|
2091
|
+
return this.reload({
|
|
2092
|
+
reason: "request_failed",
|
|
2093
|
+
context: {
|
|
2094
|
+
statusCode,
|
|
2095
|
+
},
|
|
2096
|
+
});
|
|
1738
2097
|
default:
|
|
1739
2098
|
return visit.loadResponse();
|
|
1740
2099
|
}
|
|
1741
2100
|
}
|
|
1742
|
-
visitRequestFinished(
|
|
2101
|
+
visitRequestFinished(_visit) {
|
|
1743
2102
|
this.progressBar.setValue(1);
|
|
1744
2103
|
this.hideVisitProgressBar();
|
|
1745
2104
|
}
|
|
1746
|
-
visitCompleted(
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
this.reload();
|
|
2105
|
+
visitCompleted(_visit) { }
|
|
2106
|
+
pageInvalidated(reason) {
|
|
2107
|
+
this.reload(reason);
|
|
1750
2108
|
}
|
|
1751
|
-
visitFailed(
|
|
1752
|
-
}
|
|
1753
|
-
|
|
1754
|
-
}
|
|
1755
|
-
formSubmissionStarted(formSubmission) {
|
|
2109
|
+
visitFailed(_visit) { }
|
|
2110
|
+
visitRendered(_visit) { }
|
|
2111
|
+
formSubmissionStarted(_formSubmission) {
|
|
1756
2112
|
this.progressBar.setValue(0);
|
|
1757
2113
|
this.showFormProgressBarAfterDelay();
|
|
1758
2114
|
}
|
|
1759
|
-
formSubmissionFinished(
|
|
2115
|
+
formSubmissionFinished(_formSubmission) {
|
|
1760
2116
|
this.progressBar.setValue(1);
|
|
1761
2117
|
this.hideFormProgressBar();
|
|
1762
2118
|
}
|
|
@@ -1782,8 +2138,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1782
2138
|
delete this.formProgressBarTimeout;
|
|
1783
2139
|
}
|
|
1784
2140
|
}
|
|
1785
|
-
reload() {
|
|
1786
|
-
|
|
2141
|
+
reload(reason) {
|
|
2142
|
+
var _a;
|
|
2143
|
+
dispatch("turbo:reload", { detail: reason });
|
|
2144
|
+
window.location.href = ((_a = this.location) === null || _a === void 0 ? void 0 : _a.toString()) || window.location.href;
|
|
1787
2145
|
}
|
|
1788
2146
|
get navigator() {
|
|
1789
2147
|
return this.session.navigator;
|
|
@@ -1792,95 +2150,72 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1792
2150
|
|
|
1793
2151
|
class CacheObserver {
|
|
1794
2152
|
constructor() {
|
|
2153
|
+
this.selector = "[data-turbo-temporary]";
|
|
2154
|
+
this.deprecatedSelector = "[data-turbo-cache=false]";
|
|
1795
2155
|
this.started = false;
|
|
2156
|
+
this.removeTemporaryElements = ((_event) => {
|
|
2157
|
+
for (const element of this.temporaryElements) {
|
|
2158
|
+
element.remove();
|
|
2159
|
+
}
|
|
2160
|
+
});
|
|
1796
2161
|
}
|
|
1797
2162
|
start() {
|
|
1798
2163
|
if (!this.started) {
|
|
1799
2164
|
this.started = true;
|
|
1800
|
-
addEventListener("turbo:before-cache", this.
|
|
2165
|
+
addEventListener("turbo:before-cache", this.removeTemporaryElements, false);
|
|
1801
2166
|
}
|
|
1802
2167
|
}
|
|
1803
2168
|
stop() {
|
|
1804
2169
|
if (this.started) {
|
|
1805
2170
|
this.started = false;
|
|
1806
|
-
removeEventListener("turbo:before-cache", this.
|
|
2171
|
+
removeEventListener("turbo:before-cache", this.removeTemporaryElements, false);
|
|
1807
2172
|
}
|
|
1808
2173
|
}
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
for (const element of staleElements) {
|
|
1812
|
-
element.remove();
|
|
1813
|
-
}
|
|
2174
|
+
get temporaryElements() {
|
|
2175
|
+
return [...document.querySelectorAll(this.selector), ...this.temporaryElementsWithDeprecation];
|
|
1814
2176
|
}
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
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
|
-
}
|
|
1835
|
-
}
|
|
1836
|
-
});
|
|
1837
|
-
this.delegate = delegate;
|
|
1838
|
-
}
|
|
1839
|
-
start() {
|
|
1840
|
-
if (!this.started) {
|
|
1841
|
-
addEventListener("submit", this.submitCaptured, true);
|
|
1842
|
-
this.started = true;
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
stop() {
|
|
1846
|
-
if (this.started) {
|
|
1847
|
-
removeEventListener("submit", this.submitCaptured, true);
|
|
1848
|
-
this.started = false;
|
|
2177
|
+
get temporaryElementsWithDeprecation() {
|
|
2178
|
+
const elements = document.querySelectorAll(this.deprecatedSelector);
|
|
2179
|
+
if (elements.length) {
|
|
2180
|
+
console.warn(`The ${this.deprecatedSelector} selector is deprecated and will be removed in a future version. Use ${this.selector} instead.`);
|
|
1849
2181
|
}
|
|
2182
|
+
return [...elements];
|
|
1850
2183
|
}
|
|
1851
2184
|
}
|
|
1852
2185
|
|
|
1853
2186
|
class FrameRedirector {
|
|
1854
|
-
constructor(element) {
|
|
2187
|
+
constructor(session, element) {
|
|
2188
|
+
this.session = session;
|
|
1855
2189
|
this.element = element;
|
|
1856
2190
|
this.linkInterceptor = new LinkInterceptor(this, element);
|
|
1857
|
-
this.
|
|
2191
|
+
this.formSubmitObserver = new FormSubmitObserver(this, element);
|
|
1858
2192
|
}
|
|
1859
2193
|
start() {
|
|
1860
2194
|
this.linkInterceptor.start();
|
|
1861
|
-
this.
|
|
2195
|
+
this.formSubmitObserver.start();
|
|
1862
2196
|
}
|
|
1863
2197
|
stop() {
|
|
1864
2198
|
this.linkInterceptor.stop();
|
|
1865
|
-
this.
|
|
2199
|
+
this.formSubmitObserver.stop();
|
|
1866
2200
|
}
|
|
1867
|
-
shouldInterceptLinkClick(element,
|
|
2201
|
+
shouldInterceptLinkClick(element, _location, _event) {
|
|
1868
2202
|
return this.shouldRedirect(element);
|
|
1869
2203
|
}
|
|
1870
|
-
linkClickIntercepted(element, url) {
|
|
2204
|
+
linkClickIntercepted(element, url, event) {
|
|
1871
2205
|
const frame = this.findFrameElement(element);
|
|
1872
2206
|
if (frame) {
|
|
1873
|
-
frame.delegate.linkClickIntercepted(element, url);
|
|
2207
|
+
frame.delegate.linkClickIntercepted(element, url, event);
|
|
1874
2208
|
}
|
|
1875
2209
|
}
|
|
1876
|
-
|
|
1877
|
-
return
|
|
2210
|
+
willSubmitForm(element, submitter) {
|
|
2211
|
+
return (element.closest("turbo-frame") == null &&
|
|
2212
|
+
this.shouldSubmit(element, submitter) &&
|
|
2213
|
+
this.shouldRedirect(element, submitter));
|
|
1878
2214
|
}
|
|
1879
|
-
|
|
2215
|
+
formSubmitted(element, submitter) {
|
|
1880
2216
|
const frame = this.findFrameElement(element, submitter);
|
|
1881
2217
|
if (frame) {
|
|
1882
|
-
frame.
|
|
1883
|
-
frame.delegate.formSubmissionIntercepted(element, submitter);
|
|
2218
|
+
frame.delegate.formSubmitted(element, submitter);
|
|
1884
2219
|
}
|
|
1885
2220
|
}
|
|
1886
2221
|
shouldSubmit(form, submitter) {
|
|
@@ -1891,8 +2226,16 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1891
2226
|
return this.shouldRedirect(form, submitter) && locationIsVisitable(action, rootLocation);
|
|
1892
2227
|
}
|
|
1893
2228
|
shouldRedirect(element, submitter) {
|
|
1894
|
-
const
|
|
1895
|
-
|
|
2229
|
+
const isNavigatable = element instanceof HTMLFormElement
|
|
2230
|
+
? this.session.submissionIsNavigatable(element, submitter)
|
|
2231
|
+
: this.session.elementIsNavigatable(element);
|
|
2232
|
+
if (isNavigatable) {
|
|
2233
|
+
const frame = this.findFrameElement(element, submitter);
|
|
2234
|
+
return frame ? frame != element.closest("turbo-frame") : false;
|
|
2235
|
+
}
|
|
2236
|
+
else {
|
|
2237
|
+
return false;
|
|
2238
|
+
}
|
|
1896
2239
|
}
|
|
1897
2240
|
findFrameElement(element, submitter) {
|
|
1898
2241
|
const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame");
|
|
@@ -1922,7 +2265,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1922
2265
|
}
|
|
1923
2266
|
}
|
|
1924
2267
|
};
|
|
1925
|
-
this.onPageLoad = async (
|
|
2268
|
+
this.onPageLoad = async (_event) => {
|
|
1926
2269
|
await nextMicrotask();
|
|
1927
2270
|
this.pageLoaded = true;
|
|
1928
2271
|
};
|
|
@@ -1984,63 +2327,6 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1984
2327
|
}
|
|
1985
2328
|
}
|
|
1986
2329
|
|
|
1987
|
-
class LinkClickObserver {
|
|
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
2330
|
class Navigator {
|
|
2045
2331
|
constructor(delegate) {
|
|
2046
2332
|
this.delegate = delegate;
|
|
@@ -2085,7 +2371,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2085
2371
|
return this.delegate.history;
|
|
2086
2372
|
}
|
|
2087
2373
|
formSubmissionStarted(formSubmission) {
|
|
2088
|
-
if (typeof this.adapter.formSubmissionStarted ===
|
|
2374
|
+
if (typeof this.adapter.formSubmissionStarted === "function") {
|
|
2089
2375
|
this.adapter.formSubmissionStarted(formSubmission);
|
|
2090
2376
|
}
|
|
2091
2377
|
}
|
|
@@ -2093,12 +2379,17 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2093
2379
|
if (formSubmission == this.formSubmission) {
|
|
2094
2380
|
const responseHTML = await fetchResponse.responseHTML;
|
|
2095
2381
|
if (responseHTML) {
|
|
2096
|
-
|
|
2382
|
+
const shouldCacheSnapshot = formSubmission.isSafe;
|
|
2383
|
+
if (!shouldCacheSnapshot) {
|
|
2097
2384
|
this.view.clearSnapshotCache();
|
|
2098
2385
|
}
|
|
2099
2386
|
const { statusCode, redirected } = fetchResponse;
|
|
2100
2387
|
const action = this.getActionForFormSubmission(formSubmission);
|
|
2101
|
-
const visitOptions = {
|
|
2388
|
+
const visitOptions = {
|
|
2389
|
+
action,
|
|
2390
|
+
shouldCacheSnapshot,
|
|
2391
|
+
response: { statusCode, responseHTML, redirected },
|
|
2392
|
+
};
|
|
2102
2393
|
this.proposeVisit(fetchResponse.location, visitOptions);
|
|
2103
2394
|
}
|
|
2104
2395
|
}
|
|
@@ -2108,10 +2399,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2108
2399
|
if (responseHTML) {
|
|
2109
2400
|
const snapshot = PageSnapshot.fromHTMLString(responseHTML);
|
|
2110
2401
|
if (fetchResponse.serverError) {
|
|
2111
|
-
await this.view.renderError(snapshot);
|
|
2402
|
+
await this.view.renderError(snapshot, this.currentVisit);
|
|
2112
2403
|
}
|
|
2113
2404
|
else {
|
|
2114
|
-
await this.view.renderPage(snapshot);
|
|
2405
|
+
await this.view.renderPage(snapshot, false, true, this.currentVisit);
|
|
2115
2406
|
}
|
|
2116
2407
|
this.view.scrollToTop();
|
|
2117
2408
|
this.view.clearSnapshotCache();
|
|
@@ -2121,7 +2412,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2121
2412
|
console.error(error);
|
|
2122
2413
|
}
|
|
2123
2414
|
formSubmissionFinished(formSubmission) {
|
|
2124
|
-
if (typeof this.adapter.formSubmissionFinished ===
|
|
2415
|
+
if (typeof this.adapter.formSubmissionFinished === "function") {
|
|
2125
2416
|
this.adapter.formSubmissionFinished(formSubmission);
|
|
2126
2417
|
}
|
|
2127
2418
|
}
|
|
@@ -2134,10 +2425,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2134
2425
|
locationWithActionIsSamePage(location, action) {
|
|
2135
2426
|
const anchor = getAnchor(location);
|
|
2136
2427
|
const currentAnchor = getAnchor(this.view.lastRenderedLocation);
|
|
2137
|
-
const isRestorationToTop = action ===
|
|
2138
|
-
return action !== "replace" &&
|
|
2428
|
+
const isRestorationToTop = action === "restore" && typeof anchor === "undefined";
|
|
2429
|
+
return (action !== "replace" &&
|
|
2139
2430
|
getRequestURL(location) === getRequestURL(this.view.lastRenderedLocation) &&
|
|
2140
|
-
(isRestorationToTop || (anchor != null && anchor !== currentAnchor));
|
|
2431
|
+
(isRestorationToTop || (anchor != null && anchor !== currentAnchor)));
|
|
2141
2432
|
}
|
|
2142
2433
|
visitScrolledToSamePageLocation(oldURL, newURL) {
|
|
2143
2434
|
this.delegate.visitScrolledToSamePageLocation(oldURL, newURL);
|
|
@@ -2148,10 +2439,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2148
2439
|
get restorationIdentifier() {
|
|
2149
2440
|
return this.history.restorationIdentifier;
|
|
2150
2441
|
}
|
|
2151
|
-
getActionForFormSubmission(
|
|
2152
|
-
|
|
2153
|
-
const action = getAttribute("data-turbo-action", submitter, formElement);
|
|
2154
|
-
return isAction(action) ? action : "advance";
|
|
2442
|
+
getActionForFormSubmission({ submitter, formElement }) {
|
|
2443
|
+
return getVisitAction(submitter, formElement) || "advance";
|
|
2155
2444
|
}
|
|
2156
2445
|
}
|
|
2157
2446
|
|
|
@@ -2241,9 +2530,33 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2241
2530
|
}
|
|
2242
2531
|
}
|
|
2243
2532
|
|
|
2533
|
+
class StreamMessageRenderer {
|
|
2534
|
+
render({ fragment }) {
|
|
2535
|
+
Bardo.preservingPermanentElements(this, getPermanentElementMapForFragment(fragment), () => document.documentElement.appendChild(fragment));
|
|
2536
|
+
}
|
|
2537
|
+
enteringBardo(currentPermanentElement, newPermanentElement) {
|
|
2538
|
+
newPermanentElement.replaceWith(currentPermanentElement.cloneNode(true));
|
|
2539
|
+
}
|
|
2540
|
+
leavingBardo() { }
|
|
2541
|
+
}
|
|
2542
|
+
function getPermanentElementMapForFragment(fragment) {
|
|
2543
|
+
const permanentElementsInDocument = queryPermanentElementsAll(document.documentElement);
|
|
2544
|
+
const permanentElementMap = {};
|
|
2545
|
+
for (const permanentElementInDocument of permanentElementsInDocument) {
|
|
2546
|
+
const { id } = permanentElementInDocument;
|
|
2547
|
+
for (const streamElement of fragment.querySelectorAll("turbo-stream")) {
|
|
2548
|
+
const elementInStream = getPermanentElementById(streamElement.templateElement.content, id);
|
|
2549
|
+
if (elementInStream) {
|
|
2550
|
+
permanentElementMap[id] = [permanentElementInDocument, elementInStream];
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
return permanentElementMap;
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2244
2557
|
class StreamObserver {
|
|
2245
2558
|
constructor(delegate) {
|
|
2246
|
-
this.sources = new Set;
|
|
2559
|
+
this.sources = new Set();
|
|
2247
2560
|
this.started = false;
|
|
2248
2561
|
this.inspectFetchResponse = ((event) => {
|
|
2249
2562
|
const response = fetchResponseFromEvent(event);
|
|
@@ -2293,7 +2606,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2293
2606
|
}
|
|
2294
2607
|
}
|
|
2295
2608
|
receiveMessageHTML(html) {
|
|
2296
|
-
this.delegate.receivedMessageFromStream(
|
|
2609
|
+
this.delegate.receivedMessageFromStream(StreamMessage.wrap(html));
|
|
2297
2610
|
}
|
|
2298
2611
|
}
|
|
2299
2612
|
function fetchResponseFromEvent(event) {
|
|
@@ -2310,20 +2623,24 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2310
2623
|
}
|
|
2311
2624
|
|
|
2312
2625
|
class ErrorRenderer extends Renderer {
|
|
2626
|
+
static renderElement(currentElement, newElement) {
|
|
2627
|
+
const { documentElement, body } = document;
|
|
2628
|
+
documentElement.replaceChild(newElement, body);
|
|
2629
|
+
}
|
|
2313
2630
|
async render() {
|
|
2314
2631
|
this.replaceHeadAndBody();
|
|
2315
2632
|
this.activateScriptElements();
|
|
2316
2633
|
}
|
|
2317
2634
|
replaceHeadAndBody() {
|
|
2318
|
-
const { documentElement, head
|
|
2635
|
+
const { documentElement, head } = document;
|
|
2319
2636
|
documentElement.replaceChild(this.newHead, head);
|
|
2320
|
-
|
|
2637
|
+
this.renderElement(this.currentElement, this.newElement);
|
|
2321
2638
|
}
|
|
2322
2639
|
activateScriptElements() {
|
|
2323
2640
|
for (const replaceableElement of this.scriptElements) {
|
|
2324
2641
|
const parentNode = replaceableElement.parentNode;
|
|
2325
2642
|
if (parentNode) {
|
|
2326
|
-
const element =
|
|
2643
|
+
const element = activateScriptElement(replaceableElement);
|
|
2327
2644
|
parentNode.replaceChild(element, replaceableElement);
|
|
2328
2645
|
}
|
|
2329
2646
|
}
|
|
@@ -2332,20 +2649,40 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2332
2649
|
return this.newSnapshot.headSnapshot.element;
|
|
2333
2650
|
}
|
|
2334
2651
|
get scriptElements() {
|
|
2335
|
-
return
|
|
2652
|
+
return document.documentElement.querySelectorAll("script");
|
|
2336
2653
|
}
|
|
2337
2654
|
}
|
|
2338
2655
|
|
|
2339
2656
|
class PageRenderer extends Renderer {
|
|
2657
|
+
static renderElement(currentElement, newElement) {
|
|
2658
|
+
if (document.body && newElement instanceof HTMLBodyElement) {
|
|
2659
|
+
document.body.replaceWith(newElement);
|
|
2660
|
+
}
|
|
2661
|
+
else {
|
|
2662
|
+
document.documentElement.appendChild(newElement);
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2340
2665
|
get shouldRender() {
|
|
2341
2666
|
return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical;
|
|
2342
2667
|
}
|
|
2343
|
-
|
|
2344
|
-
this.
|
|
2668
|
+
get reloadReason() {
|
|
2669
|
+
if (!this.newSnapshot.isVisitable) {
|
|
2670
|
+
return {
|
|
2671
|
+
reason: "turbo_visit_control_is_reload",
|
|
2672
|
+
};
|
|
2673
|
+
}
|
|
2674
|
+
if (!this.trackedElementsAreIdentical) {
|
|
2675
|
+
return {
|
|
2676
|
+
reason: "tracked_element_mismatch",
|
|
2677
|
+
};
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
async prepareToRender() {
|
|
2681
|
+
await this.mergeHead();
|
|
2345
2682
|
}
|
|
2346
2683
|
async render() {
|
|
2347
2684
|
if (this.willRender) {
|
|
2348
|
-
this.replaceBody();
|
|
2685
|
+
await this.replaceBody();
|
|
2349
2686
|
}
|
|
2350
2687
|
}
|
|
2351
2688
|
finishRendering() {
|
|
@@ -2363,30 +2700,63 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2363
2700
|
get newElement() {
|
|
2364
2701
|
return this.newSnapshot.element;
|
|
2365
2702
|
}
|
|
2366
|
-
mergeHead() {
|
|
2367
|
-
this.
|
|
2703
|
+
async mergeHead() {
|
|
2704
|
+
const mergedHeadElements = this.mergeProvisionalElements();
|
|
2705
|
+
const newStylesheetElements = this.copyNewHeadStylesheetElements();
|
|
2368
2706
|
this.copyNewHeadScriptElements();
|
|
2369
|
-
|
|
2370
|
-
|
|
2707
|
+
await mergedHeadElements;
|
|
2708
|
+
await newStylesheetElements;
|
|
2371
2709
|
}
|
|
2372
|
-
replaceBody() {
|
|
2373
|
-
this.preservingPermanentElements(() => {
|
|
2710
|
+
async replaceBody() {
|
|
2711
|
+
await this.preservingPermanentElements(async () => {
|
|
2374
2712
|
this.activateNewBody();
|
|
2375
|
-
this.assignNewBody();
|
|
2713
|
+
await this.assignNewBody();
|
|
2376
2714
|
});
|
|
2377
2715
|
}
|
|
2378
2716
|
get trackedElementsAreIdentical() {
|
|
2379
2717
|
return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature;
|
|
2380
2718
|
}
|
|
2381
|
-
copyNewHeadStylesheetElements() {
|
|
2719
|
+
async copyNewHeadStylesheetElements() {
|
|
2720
|
+
const loadingElements = [];
|
|
2382
2721
|
for (const element of this.newHeadStylesheetElements) {
|
|
2722
|
+
loadingElements.push(waitForLoad(element));
|
|
2383
2723
|
document.head.appendChild(element);
|
|
2384
2724
|
}
|
|
2725
|
+
await Promise.all(loadingElements);
|
|
2385
2726
|
}
|
|
2386
2727
|
copyNewHeadScriptElements() {
|
|
2387
2728
|
for (const element of this.newHeadScriptElements) {
|
|
2388
|
-
document.head.appendChild(
|
|
2729
|
+
document.head.appendChild(activateScriptElement(element));
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
async mergeProvisionalElements() {
|
|
2733
|
+
const newHeadElements = [...this.newHeadProvisionalElements];
|
|
2734
|
+
for (const element of this.currentHeadProvisionalElements) {
|
|
2735
|
+
if (!this.isCurrentElementInElementList(element, newHeadElements)) {
|
|
2736
|
+
document.head.removeChild(element);
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2739
|
+
for (const element of newHeadElements) {
|
|
2740
|
+
document.head.appendChild(element);
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
isCurrentElementInElementList(element, elementList) {
|
|
2744
|
+
for (const [index, newElement] of elementList.entries()) {
|
|
2745
|
+
if (element.tagName == "TITLE") {
|
|
2746
|
+
if (newElement.tagName != "TITLE") {
|
|
2747
|
+
continue;
|
|
2748
|
+
}
|
|
2749
|
+
if (element.innerHTML == newElement.innerHTML) {
|
|
2750
|
+
elementList.splice(index, 1);
|
|
2751
|
+
return true;
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
if (newElement.isEqualNode(element)) {
|
|
2755
|
+
elementList.splice(index, 1);
|
|
2756
|
+
return true;
|
|
2757
|
+
}
|
|
2389
2758
|
}
|
|
2759
|
+
return false;
|
|
2390
2760
|
}
|
|
2391
2761
|
removeCurrentHeadProvisionalElements() {
|
|
2392
2762
|
for (const element of this.currentHeadProvisionalElements) {
|
|
@@ -2404,17 +2774,12 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2404
2774
|
}
|
|
2405
2775
|
activateNewBodyScriptElements() {
|
|
2406
2776
|
for (const inertScriptElement of this.newBodyScriptElements) {
|
|
2407
|
-
const activatedScriptElement =
|
|
2777
|
+
const activatedScriptElement = activateScriptElement(inertScriptElement);
|
|
2408
2778
|
inertScriptElement.replaceWith(activatedScriptElement);
|
|
2409
2779
|
}
|
|
2410
2780
|
}
|
|
2411
|
-
assignNewBody() {
|
|
2412
|
-
|
|
2413
|
-
document.body.replaceWith(this.newElement);
|
|
2414
|
-
}
|
|
2415
|
-
else {
|
|
2416
|
-
document.documentElement.appendChild(this.newElement);
|
|
2417
|
-
}
|
|
2781
|
+
async assignNewBody() {
|
|
2782
|
+
await this.renderElement(this.currentElement, this.newElement);
|
|
2418
2783
|
}
|
|
2419
2784
|
get newHeadStylesheetElements() {
|
|
2420
2785
|
return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot);
|
|
@@ -2483,22 +2848,30 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2483
2848
|
super(...arguments);
|
|
2484
2849
|
this.snapshotCache = new SnapshotCache(10);
|
|
2485
2850
|
this.lastRenderedLocation = new URL(location.href);
|
|
2851
|
+
this.forceReloaded = false;
|
|
2486
2852
|
}
|
|
2487
|
-
renderPage(snapshot, isPreview = false, willRender = true) {
|
|
2488
|
-
const renderer = new PageRenderer(this.snapshot, snapshot, isPreview, willRender);
|
|
2853
|
+
renderPage(snapshot, isPreview = false, willRender = true, visit) {
|
|
2854
|
+
const renderer = new PageRenderer(this.snapshot, snapshot, PageRenderer.renderElement, isPreview, willRender);
|
|
2855
|
+
if (!renderer.shouldRender) {
|
|
2856
|
+
this.forceReloaded = true;
|
|
2857
|
+
}
|
|
2858
|
+
else {
|
|
2859
|
+
visit === null || visit === void 0 ? void 0 : visit.changeHistory();
|
|
2860
|
+
}
|
|
2489
2861
|
return this.render(renderer);
|
|
2490
2862
|
}
|
|
2491
|
-
renderError(snapshot) {
|
|
2492
|
-
|
|
2863
|
+
renderError(snapshot, visit) {
|
|
2864
|
+
visit === null || visit === void 0 ? void 0 : visit.changeHistory();
|
|
2865
|
+
const renderer = new ErrorRenderer(this.snapshot, snapshot, ErrorRenderer.renderElement, false);
|
|
2493
2866
|
return this.render(renderer);
|
|
2494
2867
|
}
|
|
2495
2868
|
clearSnapshotCache() {
|
|
2496
2869
|
this.snapshotCache.clear();
|
|
2497
2870
|
}
|
|
2498
|
-
async cacheSnapshot() {
|
|
2499
|
-
if (
|
|
2871
|
+
async cacheSnapshot(snapshot = this.snapshot) {
|
|
2872
|
+
if (snapshot.isCacheable) {
|
|
2500
2873
|
this.delegate.viewWillCacheSnapshot();
|
|
2501
|
-
const {
|
|
2874
|
+
const { lastRenderedLocation: location } = this;
|
|
2502
2875
|
await nextEventLoopTick();
|
|
2503
2876
|
const cachedSnapshot = snapshot.clone();
|
|
2504
2877
|
this.snapshotCache.put(location, cachedSnapshot);
|
|
@@ -2511,8 +2884,44 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2511
2884
|
get snapshot() {
|
|
2512
2885
|
return PageSnapshot.fromElement(this.element);
|
|
2513
2886
|
}
|
|
2514
|
-
|
|
2515
|
-
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2889
|
+
class Preloader {
|
|
2890
|
+
constructor(delegate) {
|
|
2891
|
+
this.selector = "a[data-turbo-preload]";
|
|
2892
|
+
this.delegate = delegate;
|
|
2893
|
+
}
|
|
2894
|
+
get snapshotCache() {
|
|
2895
|
+
return this.delegate.navigator.view.snapshotCache;
|
|
2896
|
+
}
|
|
2897
|
+
start() {
|
|
2898
|
+
if (document.readyState === "loading") {
|
|
2899
|
+
return document.addEventListener("DOMContentLoaded", () => {
|
|
2900
|
+
this.preloadOnLoadLinksForView(document.body);
|
|
2901
|
+
});
|
|
2902
|
+
}
|
|
2903
|
+
else {
|
|
2904
|
+
this.preloadOnLoadLinksForView(document.body);
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
preloadOnLoadLinksForView(element) {
|
|
2908
|
+
for (const link of element.querySelectorAll(this.selector)) {
|
|
2909
|
+
this.preloadURL(link);
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
async preloadURL(link) {
|
|
2913
|
+
const location = new URL(link.href);
|
|
2914
|
+
if (this.snapshotCache.has(location)) {
|
|
2915
|
+
return;
|
|
2916
|
+
}
|
|
2917
|
+
try {
|
|
2918
|
+
const response = await fetch(location.toString(), { headers: { "VND.PREFETCH": "true", Accept: "text/html" } });
|
|
2919
|
+
const responseText = await response.text();
|
|
2920
|
+
const snapshot = PageSnapshot.fromHTMLString(responseText);
|
|
2921
|
+
this.snapshotCache.put(location, snapshot);
|
|
2922
|
+
}
|
|
2923
|
+
catch (_) {
|
|
2924
|
+
}
|
|
2516
2925
|
}
|
|
2517
2926
|
}
|
|
2518
2927
|
|
|
@@ -2520,30 +2929,36 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2520
2929
|
constructor() {
|
|
2521
2930
|
this.navigator = new Navigator(this);
|
|
2522
2931
|
this.history = new History(this);
|
|
2932
|
+
this.preloader = new Preloader(this);
|
|
2523
2933
|
this.view = new PageView(this, document.documentElement);
|
|
2524
2934
|
this.adapter = new BrowserAdapter(this);
|
|
2525
2935
|
this.pageObserver = new PageObserver(this);
|
|
2526
2936
|
this.cacheObserver = new CacheObserver();
|
|
2527
|
-
this.linkClickObserver = new LinkClickObserver(this);
|
|
2528
|
-
this.formSubmitObserver = new FormSubmitObserver(this);
|
|
2937
|
+
this.linkClickObserver = new LinkClickObserver(this, window);
|
|
2938
|
+
this.formSubmitObserver = new FormSubmitObserver(this, document);
|
|
2529
2939
|
this.scrollObserver = new ScrollObserver(this);
|
|
2530
2940
|
this.streamObserver = new StreamObserver(this);
|
|
2531
|
-
this.
|
|
2941
|
+
this.formLinkClickObserver = new FormLinkClickObserver(this, document.documentElement);
|
|
2942
|
+
this.frameRedirector = new FrameRedirector(this, document.documentElement);
|
|
2943
|
+
this.streamMessageRenderer = new StreamMessageRenderer();
|
|
2532
2944
|
this.drive = true;
|
|
2533
2945
|
this.enabled = true;
|
|
2534
2946
|
this.progressBarDelay = 500;
|
|
2535
2947
|
this.started = false;
|
|
2948
|
+
this.formMode = "on";
|
|
2536
2949
|
}
|
|
2537
2950
|
start() {
|
|
2538
2951
|
if (!this.started) {
|
|
2539
2952
|
this.pageObserver.start();
|
|
2540
2953
|
this.cacheObserver.start();
|
|
2954
|
+
this.formLinkClickObserver.start();
|
|
2541
2955
|
this.linkClickObserver.start();
|
|
2542
2956
|
this.formSubmitObserver.start();
|
|
2543
2957
|
this.scrollObserver.start();
|
|
2544
2958
|
this.streamObserver.start();
|
|
2545
2959
|
this.frameRedirector.start();
|
|
2546
2960
|
this.history.start();
|
|
2961
|
+
this.preloader.start();
|
|
2547
2962
|
this.started = true;
|
|
2548
2963
|
this.enabled = true;
|
|
2549
2964
|
}
|
|
@@ -2555,6 +2970,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2555
2970
|
if (this.started) {
|
|
2556
2971
|
this.pageObserver.stop();
|
|
2557
2972
|
this.cacheObserver.stop();
|
|
2973
|
+
this.formLinkClickObserver.stop();
|
|
2558
2974
|
this.linkClickObserver.stop();
|
|
2559
2975
|
this.formSubmitObserver.stop();
|
|
2560
2976
|
this.scrollObserver.stop();
|
|
@@ -2568,7 +2984,14 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2568
2984
|
this.adapter = adapter;
|
|
2569
2985
|
}
|
|
2570
2986
|
visit(location, options = {}) {
|
|
2571
|
-
|
|
2987
|
+
const frameElement = options.frame ? document.getElementById(options.frame) : null;
|
|
2988
|
+
if (frameElement instanceof FrameElement) {
|
|
2989
|
+
frameElement.src = location.toString();
|
|
2990
|
+
frameElement.loaded;
|
|
2991
|
+
}
|
|
2992
|
+
else {
|
|
2993
|
+
this.navigator.proposeVisit(expandURL(location), options);
|
|
2994
|
+
}
|
|
2572
2995
|
}
|
|
2573
2996
|
connectStreamSource(source) {
|
|
2574
2997
|
this.streamObserver.connectStreamSource(source);
|
|
@@ -2577,7 +3000,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2577
3000
|
this.streamObserver.disconnectStreamSource(source);
|
|
2578
3001
|
}
|
|
2579
3002
|
renderStreamMessage(message) {
|
|
2580
|
-
|
|
3003
|
+
this.streamMessageRenderer.render(StreamMessage.wrap(message));
|
|
2581
3004
|
}
|
|
2582
3005
|
clearCache() {
|
|
2583
3006
|
this.view.clearSnapshotCache();
|
|
@@ -2585,6 +3008,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2585
3008
|
setProgressBarDelay(delay) {
|
|
2586
3009
|
this.progressBarDelay = delay;
|
|
2587
3010
|
}
|
|
3011
|
+
setFormMode(mode) {
|
|
3012
|
+
this.formMode = mode;
|
|
3013
|
+
}
|
|
2588
3014
|
get location() {
|
|
2589
3015
|
return this.history.location;
|
|
2590
3016
|
}
|
|
@@ -2593,48 +3019,33 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2593
3019
|
}
|
|
2594
3020
|
historyPoppedToLocationWithRestorationIdentifier(location, restorationIdentifier) {
|
|
2595
3021
|
if (this.enabled) {
|
|
2596
|
-
this.navigator.startVisit(location, restorationIdentifier, {
|
|
3022
|
+
this.navigator.startVisit(location, restorationIdentifier, {
|
|
3023
|
+
action: "restore",
|
|
3024
|
+
historyChanged: true,
|
|
3025
|
+
});
|
|
2597
3026
|
}
|
|
2598
3027
|
else {
|
|
2599
|
-
this.adapter.pageInvalidated(
|
|
3028
|
+
this.adapter.pageInvalidated({
|
|
3029
|
+
reason: "turbo_disabled",
|
|
3030
|
+
});
|
|
2600
3031
|
}
|
|
2601
3032
|
}
|
|
2602
3033
|
scrollPositionChanged(position) {
|
|
2603
3034
|
this.history.updateRestorationData({ scrollPosition: position });
|
|
2604
3035
|
}
|
|
2605
|
-
|
|
2606
|
-
return this.
|
|
2607
|
-
|
|
2608
|
-
|
|
3036
|
+
willSubmitFormLinkToLocation(link, location) {
|
|
3037
|
+
return this.elementIsNavigatable(link) && locationIsVisitable(location, this.snapshot.rootLocation);
|
|
3038
|
+
}
|
|
3039
|
+
submittedFormLinkToLocation() { }
|
|
3040
|
+
willFollowLinkToLocation(link, location, event) {
|
|
3041
|
+
return (this.elementIsNavigatable(link) &&
|
|
3042
|
+
locationIsVisitable(location, this.snapshot.rootLocation) &&
|
|
3043
|
+
this.applicationAllowsFollowingLinkToLocation(link, location, event));
|
|
2609
3044
|
}
|
|
2610
3045
|
followedLinkToLocation(link, location) {
|
|
2611
3046
|
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
|
-
}
|
|
3047
|
+
const acceptsStreamResponse = link.hasAttribute("data-turbo-stream");
|
|
3048
|
+
this.visit(location.href, { action, acceptsStreamResponse });
|
|
2638
3049
|
}
|
|
2639
3050
|
allowsVisitingLocationWithAction(location, action) {
|
|
2640
3051
|
return this.locationWithActionIsSamePage(location, action) || this.applicationAllowsVisitingLocation(location);
|
|
@@ -2644,12 +3055,16 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2644
3055
|
this.adapter.visitProposedToLocation(location, options);
|
|
2645
3056
|
}
|
|
2646
3057
|
visitStarted(visit) {
|
|
3058
|
+
if (!visit.acceptsStreamResponse) {
|
|
3059
|
+
markAsBusy(document.documentElement);
|
|
3060
|
+
}
|
|
2647
3061
|
extendURLWithDeprecatedProperties(visit.location);
|
|
2648
3062
|
if (!visit.silent) {
|
|
2649
3063
|
this.notifyApplicationAfterVisitingLocation(visit.location, visit.action);
|
|
2650
3064
|
}
|
|
2651
3065
|
}
|
|
2652
3066
|
visitCompleted(visit) {
|
|
3067
|
+
clearBusyState(document.documentElement);
|
|
2653
3068
|
this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());
|
|
2654
3069
|
}
|
|
2655
3070
|
locationWithActionIsSamePage(location, action) {
|
|
@@ -2660,9 +3075,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2660
3075
|
}
|
|
2661
3076
|
willSubmitForm(form, submitter) {
|
|
2662
3077
|
const action = getAction(form, submitter);
|
|
2663
|
-
return this.
|
|
2664
|
-
|
|
2665
|
-
&& locationIsVisitable(expandURL(action), this.snapshot.rootLocation);
|
|
3078
|
+
return (this.submissionIsNavigatable(form, submitter) &&
|
|
3079
|
+
locationIsVisitable(expandURL(action), this.snapshot.rootLocation));
|
|
2666
3080
|
}
|
|
2667
3081
|
formSubmitted(form, submitter) {
|
|
2668
3082
|
this.navigator.submitForm(form, submitter);
|
|
@@ -2686,16 +3100,23 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2686
3100
|
this.notifyApplicationBeforeCachingSnapshot();
|
|
2687
3101
|
}
|
|
2688
3102
|
}
|
|
2689
|
-
allowsImmediateRender({ element },
|
|
2690
|
-
const event = this.notifyApplicationBeforeRender(element,
|
|
2691
|
-
|
|
3103
|
+
allowsImmediateRender({ element }, options) {
|
|
3104
|
+
const event = this.notifyApplicationBeforeRender(element, options);
|
|
3105
|
+
const { defaultPrevented, detail: { render }, } = event;
|
|
3106
|
+
if (this.view.renderer && render) {
|
|
3107
|
+
this.view.renderer.renderElement = render;
|
|
3108
|
+
}
|
|
3109
|
+
return !defaultPrevented;
|
|
2692
3110
|
}
|
|
2693
|
-
viewRenderedSnapshot(
|
|
3111
|
+
viewRenderedSnapshot(_snapshot, _isPreview) {
|
|
2694
3112
|
this.view.lastRenderedLocation = this.history.location;
|
|
2695
3113
|
this.notifyApplicationAfterRender();
|
|
2696
3114
|
}
|
|
2697
|
-
|
|
2698
|
-
this.
|
|
3115
|
+
preloadOnLoadLinksForView(element) {
|
|
3116
|
+
this.preloader.preloadOnLoadLinksForView(element);
|
|
3117
|
+
}
|
|
3118
|
+
viewInvalidated(reason) {
|
|
3119
|
+
this.adapter.pageInvalidated(reason);
|
|
2699
3120
|
}
|
|
2700
3121
|
frameLoaded(frame) {
|
|
2701
3122
|
this.notifyApplicationAfterFrameLoad(frame);
|
|
@@ -2703,49 +3124,81 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2703
3124
|
frameRendered(fetchResponse, frame) {
|
|
2704
3125
|
this.notifyApplicationAfterFrameRender(fetchResponse, frame);
|
|
2705
3126
|
}
|
|
2706
|
-
applicationAllowsFollowingLinkToLocation(link, location) {
|
|
2707
|
-
const event = this.notifyApplicationAfterClickingLinkToLocation(link, location);
|
|
3127
|
+
applicationAllowsFollowingLinkToLocation(link, location, ev) {
|
|
3128
|
+
const event = this.notifyApplicationAfterClickingLinkToLocation(link, location, ev);
|
|
2708
3129
|
return !event.defaultPrevented;
|
|
2709
3130
|
}
|
|
2710
3131
|
applicationAllowsVisitingLocation(location) {
|
|
2711
3132
|
const event = this.notifyApplicationBeforeVisitingLocation(location);
|
|
2712
3133
|
return !event.defaultPrevented;
|
|
2713
3134
|
}
|
|
2714
|
-
notifyApplicationAfterClickingLinkToLocation(link, location) {
|
|
2715
|
-
return dispatch("turbo:click", {
|
|
3135
|
+
notifyApplicationAfterClickingLinkToLocation(link, location, event) {
|
|
3136
|
+
return dispatch("turbo:click", {
|
|
3137
|
+
target: link,
|
|
3138
|
+
detail: { url: location.href, originalEvent: event },
|
|
3139
|
+
cancelable: true,
|
|
3140
|
+
});
|
|
2716
3141
|
}
|
|
2717
3142
|
notifyApplicationBeforeVisitingLocation(location) {
|
|
2718
|
-
return dispatch("turbo:before-visit", {
|
|
3143
|
+
return dispatch("turbo:before-visit", {
|
|
3144
|
+
detail: { url: location.href },
|
|
3145
|
+
cancelable: true,
|
|
3146
|
+
});
|
|
2719
3147
|
}
|
|
2720
3148
|
notifyApplicationAfterVisitingLocation(location, action) {
|
|
2721
|
-
markAsBusy(document.documentElement);
|
|
2722
3149
|
return dispatch("turbo:visit", { detail: { url: location.href, action } });
|
|
2723
3150
|
}
|
|
2724
3151
|
notifyApplicationBeforeCachingSnapshot() {
|
|
2725
3152
|
return dispatch("turbo:before-cache");
|
|
2726
3153
|
}
|
|
2727
|
-
notifyApplicationBeforeRender(newBody,
|
|
2728
|
-
return dispatch("turbo:before-render", {
|
|
3154
|
+
notifyApplicationBeforeRender(newBody, options) {
|
|
3155
|
+
return dispatch("turbo:before-render", {
|
|
3156
|
+
detail: Object.assign({ newBody }, options),
|
|
3157
|
+
cancelable: true,
|
|
3158
|
+
});
|
|
2729
3159
|
}
|
|
2730
3160
|
notifyApplicationAfterRender() {
|
|
2731
3161
|
return dispatch("turbo:render");
|
|
2732
3162
|
}
|
|
2733
3163
|
notifyApplicationAfterPageLoad(timing = {}) {
|
|
2734
|
-
|
|
2735
|
-
|
|
3164
|
+
return dispatch("turbo:load", {
|
|
3165
|
+
detail: { url: this.location.href, timing },
|
|
3166
|
+
});
|
|
2736
3167
|
}
|
|
2737
3168
|
notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL) {
|
|
2738
|
-
dispatchEvent(new HashChangeEvent("hashchange", {
|
|
3169
|
+
dispatchEvent(new HashChangeEvent("hashchange", {
|
|
3170
|
+
oldURL: oldURL.toString(),
|
|
3171
|
+
newURL: newURL.toString(),
|
|
3172
|
+
}));
|
|
2739
3173
|
}
|
|
2740
3174
|
notifyApplicationAfterFrameLoad(frame) {
|
|
2741
3175
|
return dispatch("turbo:frame-load", { target: frame });
|
|
2742
3176
|
}
|
|
2743
3177
|
notifyApplicationAfterFrameRender(fetchResponse, frame) {
|
|
2744
|
-
return dispatch("turbo:frame-render", {
|
|
3178
|
+
return dispatch("turbo:frame-render", {
|
|
3179
|
+
detail: { fetchResponse },
|
|
3180
|
+
target: frame,
|
|
3181
|
+
cancelable: true,
|
|
3182
|
+
});
|
|
3183
|
+
}
|
|
3184
|
+
submissionIsNavigatable(form, submitter) {
|
|
3185
|
+
if (this.formMode == "off") {
|
|
3186
|
+
return false;
|
|
3187
|
+
}
|
|
3188
|
+
else {
|
|
3189
|
+
const submitterIsNavigatable = submitter ? this.elementIsNavigatable(submitter) : true;
|
|
3190
|
+
if (this.formMode == "optin") {
|
|
3191
|
+
return submitterIsNavigatable && form.closest('[data-turbo="true"]') != null;
|
|
3192
|
+
}
|
|
3193
|
+
else {
|
|
3194
|
+
return submitterIsNavigatable && this.elementIsNavigatable(form);
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
2745
3197
|
}
|
|
2746
|
-
|
|
2747
|
-
const container = element
|
|
2748
|
-
|
|
3198
|
+
elementIsNavigatable(element) {
|
|
3199
|
+
const container = findClosestRecursively(element, "[data-turbo]");
|
|
3200
|
+
const withinFrame = findClosestRecursively(element, "turbo-frame");
|
|
3201
|
+
if (this.drive || withinFrame) {
|
|
2749
3202
|
if (container) {
|
|
2750
3203
|
return container.getAttribute("data-turbo") != "false";
|
|
2751
3204
|
}
|
|
@@ -2763,20 +3216,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2763
3216
|
}
|
|
2764
3217
|
}
|
|
2765
3218
|
getActionForLink(link) {
|
|
2766
|
-
|
|
2767
|
-
return isAction(action) ? action : "advance";
|
|
2768
|
-
}
|
|
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
|
-
}
|
|
3219
|
+
return getVisitAction(link) || "advance";
|
|
2780
3220
|
}
|
|
2781
3221
|
get snapshot() {
|
|
2782
3222
|
return this.view.snapshot;
|
|
@@ -2789,11 +3229,62 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2789
3229
|
absoluteURL: {
|
|
2790
3230
|
get() {
|
|
2791
3231
|
return this.toString();
|
|
2792
|
-
}
|
|
3232
|
+
},
|
|
3233
|
+
},
|
|
3234
|
+
};
|
|
3235
|
+
|
|
3236
|
+
class Cache {
|
|
3237
|
+
constructor(session) {
|
|
3238
|
+
this.session = session;
|
|
2793
3239
|
}
|
|
3240
|
+
clear() {
|
|
3241
|
+
this.session.clearCache();
|
|
3242
|
+
}
|
|
3243
|
+
resetCacheControl() {
|
|
3244
|
+
this.setCacheControl("");
|
|
3245
|
+
}
|
|
3246
|
+
exemptPageFromCache() {
|
|
3247
|
+
this.setCacheControl("no-cache");
|
|
3248
|
+
}
|
|
3249
|
+
exemptPageFromPreview() {
|
|
3250
|
+
this.setCacheControl("no-preview");
|
|
3251
|
+
}
|
|
3252
|
+
setCacheControl(value) {
|
|
3253
|
+
setMetaContent("turbo-cache-control", value);
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
const StreamActions = {
|
|
3258
|
+
after() {
|
|
3259
|
+
this.targetElements.forEach((e) => { var _a; return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e.nextSibling); });
|
|
3260
|
+
},
|
|
3261
|
+
append() {
|
|
3262
|
+
this.removeDuplicateTargetChildren();
|
|
3263
|
+
this.targetElements.forEach((e) => e.append(this.templateContent));
|
|
3264
|
+
},
|
|
3265
|
+
before() {
|
|
3266
|
+
this.targetElements.forEach((e) => { var _a; return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e); });
|
|
3267
|
+
},
|
|
3268
|
+
prepend() {
|
|
3269
|
+
this.removeDuplicateTargetChildren();
|
|
3270
|
+
this.targetElements.forEach((e) => e.prepend(this.templateContent));
|
|
3271
|
+
},
|
|
3272
|
+
remove() {
|
|
3273
|
+
this.targetElements.forEach((e) => e.remove());
|
|
3274
|
+
},
|
|
3275
|
+
replace() {
|
|
3276
|
+
this.targetElements.forEach((e) => e.replaceWith(this.templateContent));
|
|
3277
|
+
},
|
|
3278
|
+
update() {
|
|
3279
|
+
this.targetElements.forEach((targetElement) => {
|
|
3280
|
+
targetElement.innerHTML = "";
|
|
3281
|
+
targetElement.append(this.templateContent);
|
|
3282
|
+
});
|
|
3283
|
+
},
|
|
2794
3284
|
};
|
|
2795
3285
|
|
|
2796
|
-
const session = new Session;
|
|
3286
|
+
const session = new Session();
|
|
3287
|
+
const cache = new Cache(session);
|
|
2797
3288
|
const { navigator: navigator$1 } = session;
|
|
2798
3289
|
function start() {
|
|
2799
3290
|
session.start();
|
|
@@ -2814,6 +3305,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2814
3305
|
session.renderStreamMessage(message);
|
|
2815
3306
|
}
|
|
2816
3307
|
function clearCache() {
|
|
3308
|
+
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
3309
|
session.clearCache();
|
|
2818
3310
|
}
|
|
2819
3311
|
function setProgressBarDelay(delay) {
|
|
@@ -2822,13 +3314,18 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2822
3314
|
function setConfirmMethod(confirmMethod) {
|
|
2823
3315
|
FormSubmission.confirmMethod = confirmMethod;
|
|
2824
3316
|
}
|
|
3317
|
+
function setFormMode(mode) {
|
|
3318
|
+
session.setFormMode(mode);
|
|
3319
|
+
}
|
|
2825
3320
|
|
|
2826
3321
|
var Turbo = /*#__PURE__*/Object.freeze({
|
|
2827
3322
|
__proto__: null,
|
|
2828
3323
|
navigator: navigator$1,
|
|
2829
3324
|
session: session,
|
|
3325
|
+
cache: cache,
|
|
2830
3326
|
PageRenderer: PageRenderer,
|
|
2831
3327
|
PageSnapshot: PageSnapshot,
|
|
3328
|
+
FrameRenderer: FrameRenderer,
|
|
2832
3329
|
start: start,
|
|
2833
3330
|
registerAdapter: registerAdapter,
|
|
2834
3331
|
visit: visit,
|
|
@@ -2837,55 +3334,92 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2837
3334
|
renderStreamMessage: renderStreamMessage,
|
|
2838
3335
|
clearCache: clearCache,
|
|
2839
3336
|
setProgressBarDelay: setProgressBarDelay,
|
|
2840
|
-
setConfirmMethod: setConfirmMethod
|
|
3337
|
+
setConfirmMethod: setConfirmMethod,
|
|
3338
|
+
setFormMode: setFormMode,
|
|
3339
|
+
StreamActions: StreamActions
|
|
2841
3340
|
});
|
|
2842
3341
|
|
|
3342
|
+
class TurboFrameMissingError extends Error {
|
|
3343
|
+
}
|
|
3344
|
+
|
|
2843
3345
|
class FrameController {
|
|
2844
3346
|
constructor(element) {
|
|
2845
|
-
this.fetchResponseLoaded = (
|
|
3347
|
+
this.fetchResponseLoaded = (_fetchResponse) => { };
|
|
2846
3348
|
this.currentFetchRequest = null;
|
|
2847
3349
|
this.resolveVisitPromise = () => { };
|
|
2848
3350
|
this.connected = false;
|
|
2849
3351
|
this.hasBeenLoaded = false;
|
|
2850
|
-
this.
|
|
3352
|
+
this.ignoredAttributes = new Set();
|
|
3353
|
+
this.action = null;
|
|
3354
|
+
this.visitCachedSnapshot = ({ element }) => {
|
|
3355
|
+
const frame = element.querySelector("#" + this.element.id);
|
|
3356
|
+
if (frame && this.previousFrameElement) {
|
|
3357
|
+
frame.replaceChildren(...this.previousFrameElement.children);
|
|
3358
|
+
}
|
|
3359
|
+
delete this.previousFrameElement;
|
|
3360
|
+
};
|
|
2851
3361
|
this.element = element;
|
|
2852
3362
|
this.view = new FrameView(this, this.element);
|
|
2853
3363
|
this.appearanceObserver = new AppearanceObserver(this, this.element);
|
|
3364
|
+
this.formLinkClickObserver = new FormLinkClickObserver(this, this.element);
|
|
2854
3365
|
this.linkInterceptor = new LinkInterceptor(this, this.element);
|
|
2855
|
-
this.
|
|
3366
|
+
this.restorationIdentifier = uuid();
|
|
3367
|
+
this.formSubmitObserver = new FormSubmitObserver(this, this.element);
|
|
2856
3368
|
}
|
|
2857
3369
|
connect() {
|
|
2858
3370
|
if (!this.connected) {
|
|
2859
3371
|
this.connected = true;
|
|
2860
|
-
this.
|
|
2861
|
-
if (this.loadingStyle == FrameLoadingStyle.lazy) {
|
|
3372
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.lazy) {
|
|
2862
3373
|
this.appearanceObserver.start();
|
|
2863
3374
|
}
|
|
3375
|
+
else {
|
|
3376
|
+
this.loadSourceURL();
|
|
3377
|
+
}
|
|
3378
|
+
this.formLinkClickObserver.start();
|
|
2864
3379
|
this.linkInterceptor.start();
|
|
2865
|
-
this.
|
|
2866
|
-
this.sourceURLChanged();
|
|
3380
|
+
this.formSubmitObserver.start();
|
|
2867
3381
|
}
|
|
2868
3382
|
}
|
|
2869
3383
|
disconnect() {
|
|
2870
3384
|
if (this.connected) {
|
|
2871
3385
|
this.connected = false;
|
|
2872
3386
|
this.appearanceObserver.stop();
|
|
3387
|
+
this.formLinkClickObserver.stop();
|
|
2873
3388
|
this.linkInterceptor.stop();
|
|
2874
|
-
this.
|
|
3389
|
+
this.formSubmitObserver.stop();
|
|
2875
3390
|
}
|
|
2876
3391
|
}
|
|
2877
3392
|
disabledChanged() {
|
|
2878
|
-
if (this.loadingStyle == FrameLoadingStyle.eager) {
|
|
3393
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.eager) {
|
|
2879
3394
|
this.loadSourceURL();
|
|
2880
3395
|
}
|
|
2881
3396
|
}
|
|
2882
3397
|
sourceURLChanged() {
|
|
2883
|
-
if (this.
|
|
3398
|
+
if (this.isIgnoringChangesTo("src"))
|
|
3399
|
+
return;
|
|
3400
|
+
if (this.element.isConnected) {
|
|
3401
|
+
this.complete = false;
|
|
3402
|
+
}
|
|
3403
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.eager || this.hasBeenLoaded) {
|
|
2884
3404
|
this.loadSourceURL();
|
|
2885
3405
|
}
|
|
2886
3406
|
}
|
|
3407
|
+
sourceURLReloaded() {
|
|
3408
|
+
const { src } = this.element;
|
|
3409
|
+
this.ignoringChangesToAttribute("complete", () => {
|
|
3410
|
+
this.element.removeAttribute("complete");
|
|
3411
|
+
});
|
|
3412
|
+
this.element.src = null;
|
|
3413
|
+
this.element.src = src;
|
|
3414
|
+
return this.element.loaded;
|
|
3415
|
+
}
|
|
3416
|
+
completeChanged() {
|
|
3417
|
+
if (this.isIgnoringChangesTo("complete"))
|
|
3418
|
+
return;
|
|
3419
|
+
this.loadSourceURL();
|
|
3420
|
+
}
|
|
2887
3421
|
loadingStyleChanged() {
|
|
2888
|
-
if (this.loadingStyle == FrameLoadingStyle.lazy) {
|
|
3422
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.lazy) {
|
|
2889
3423
|
this.appearanceObserver.start();
|
|
2890
3424
|
}
|
|
2891
3425
|
else {
|
|
@@ -2894,21 +3428,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2894
3428
|
}
|
|
2895
3429
|
}
|
|
2896
3430
|
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
|
-
}
|
|
3431
|
+
if (this.enabled && this.isActive && !this.complete && this.sourceURL) {
|
|
3432
|
+
this.element.loaded = this.visit(expandURL(this.sourceURL));
|
|
3433
|
+
this.appearanceObserver.stop();
|
|
3434
|
+
await this.element.loaded;
|
|
3435
|
+
this.hasBeenLoaded = true;
|
|
2912
3436
|
}
|
|
2913
3437
|
}
|
|
2914
3438
|
async loadResponse(fetchResponse) {
|
|
@@ -2918,75 +3442,76 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2918
3442
|
try {
|
|
2919
3443
|
const html = await fetchResponse.responseHTML;
|
|
2920
3444
|
if (html) {
|
|
2921
|
-
const
|
|
2922
|
-
const
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
this.fetchResponseLoaded(fetchResponse);
|
|
3445
|
+
const document = parseHTMLDocument(html);
|
|
3446
|
+
const pageSnapshot = PageSnapshot.fromDocument(document);
|
|
3447
|
+
if (pageSnapshot.isVisitable) {
|
|
3448
|
+
await this.loadFrameResponse(fetchResponse, document);
|
|
3449
|
+
}
|
|
3450
|
+
else {
|
|
3451
|
+
await this.handleUnvisitableFrameResponse(fetchResponse);
|
|
3452
|
+
}
|
|
2930
3453
|
}
|
|
2931
3454
|
}
|
|
2932
|
-
catch (error) {
|
|
2933
|
-
console.error(error);
|
|
2934
|
-
this.view.invalidate();
|
|
2935
|
-
}
|
|
2936
3455
|
finally {
|
|
2937
3456
|
this.fetchResponseLoaded = () => { };
|
|
2938
3457
|
}
|
|
2939
3458
|
}
|
|
2940
3459
|
elementAppearedInViewport(element) {
|
|
3460
|
+
this.proposeVisitIfNavigatedWithAction(element, element);
|
|
2941
3461
|
this.loadSourceURL();
|
|
2942
3462
|
}
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
return false;
|
|
2946
|
-
}
|
|
2947
|
-
else {
|
|
2948
|
-
return this.shouldInterceptNavigation(element);
|
|
2949
|
-
}
|
|
3463
|
+
willSubmitFormLinkToLocation(link) {
|
|
3464
|
+
return this.shouldInterceptNavigation(link);
|
|
2950
3465
|
}
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
3466
|
+
submittedFormLinkToLocation(link, _location, form) {
|
|
3467
|
+
const frame = this.findFrameElement(link);
|
|
3468
|
+
if (frame)
|
|
3469
|
+
form.setAttribute("data-turbo-frame", frame.id);
|
|
2954
3470
|
}
|
|
2955
|
-
|
|
2956
|
-
return this.shouldInterceptNavigation(element
|
|
3471
|
+
shouldInterceptLinkClick(element, _location, _event) {
|
|
3472
|
+
return this.shouldInterceptNavigation(element);
|
|
2957
3473
|
}
|
|
2958
|
-
|
|
3474
|
+
linkClickIntercepted(element, location) {
|
|
3475
|
+
this.navigateFrame(element, location);
|
|
3476
|
+
}
|
|
3477
|
+
willSubmitForm(element, submitter) {
|
|
3478
|
+
return element.closest("turbo-frame") == this.element && this.shouldInterceptNavigation(element, submitter);
|
|
3479
|
+
}
|
|
3480
|
+
formSubmitted(element, submitter) {
|
|
2959
3481
|
if (this.formSubmission) {
|
|
2960
3482
|
this.formSubmission.stop();
|
|
2961
3483
|
}
|
|
2962
|
-
this.reloadable = false;
|
|
2963
3484
|
this.formSubmission = new FormSubmission(this, element, submitter);
|
|
2964
3485
|
const { fetchRequest } = this.formSubmission;
|
|
2965
|
-
this.
|
|
3486
|
+
this.prepareRequest(fetchRequest);
|
|
2966
3487
|
this.formSubmission.start();
|
|
2967
3488
|
}
|
|
2968
|
-
|
|
2969
|
-
|
|
3489
|
+
prepareRequest(request) {
|
|
3490
|
+
var _a;
|
|
3491
|
+
request.headers["Turbo-Frame"] = this.id;
|
|
3492
|
+
if ((_a = this.currentNavigationElement) === null || _a === void 0 ? void 0 : _a.hasAttribute("data-turbo-stream")) {
|
|
3493
|
+
request.acceptResponseType(StreamMessage.contentType);
|
|
3494
|
+
}
|
|
2970
3495
|
}
|
|
2971
|
-
requestStarted(
|
|
3496
|
+
requestStarted(_request) {
|
|
2972
3497
|
markAsBusy(this.element);
|
|
2973
3498
|
}
|
|
2974
|
-
requestPreventedHandlingResponse(
|
|
3499
|
+
requestPreventedHandlingResponse(_request, _response) {
|
|
2975
3500
|
this.resolveVisitPromise();
|
|
2976
3501
|
}
|
|
2977
3502
|
async requestSucceededWithResponse(request, response) {
|
|
2978
3503
|
await this.loadResponse(response);
|
|
2979
3504
|
this.resolveVisitPromise();
|
|
2980
3505
|
}
|
|
2981
|
-
requestFailedWithResponse(request, response) {
|
|
2982
|
-
|
|
3506
|
+
async requestFailedWithResponse(request, response) {
|
|
3507
|
+
await this.loadResponse(response);
|
|
2983
3508
|
this.resolveVisitPromise();
|
|
2984
3509
|
}
|
|
2985
3510
|
requestErrored(request, error) {
|
|
2986
3511
|
console.error(error);
|
|
2987
3512
|
this.resolveVisitPromise();
|
|
2988
3513
|
}
|
|
2989
|
-
requestFinished(
|
|
3514
|
+
requestFinished(_request) {
|
|
2990
3515
|
clearBusyState(this.element);
|
|
2991
3516
|
}
|
|
2992
3517
|
formSubmissionStarted({ formElement }) {
|
|
@@ -2994,11 +3519,15 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2994
3519
|
}
|
|
2995
3520
|
formSubmissionSucceededWithResponse(formSubmission, response) {
|
|
2996
3521
|
const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter);
|
|
2997
|
-
|
|
3522
|
+
frame.delegate.proposeVisitIfNavigatedWithAction(frame, formSubmission.formElement, formSubmission.submitter);
|
|
2998
3523
|
frame.delegate.loadResponse(response);
|
|
3524
|
+
if (!formSubmission.isSafe) {
|
|
3525
|
+
session.clearCache();
|
|
3526
|
+
}
|
|
2999
3527
|
}
|
|
3000
3528
|
formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
|
|
3001
3529
|
this.element.delegate.loadResponse(fetchResponse);
|
|
3530
|
+
session.clearCache();
|
|
3002
3531
|
}
|
|
3003
3532
|
formSubmissionErrored(formSubmission, error) {
|
|
3004
3533
|
console.error(error);
|
|
@@ -3006,19 +3535,50 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3006
3535
|
formSubmissionFinished({ formElement }) {
|
|
3007
3536
|
clearBusyState(formElement, this.findFrameElement(formElement));
|
|
3008
3537
|
}
|
|
3009
|
-
allowsImmediateRender(
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3538
|
+
allowsImmediateRender({ element: newFrame }, options) {
|
|
3539
|
+
const event = dispatch("turbo:before-frame-render", {
|
|
3540
|
+
target: this.element,
|
|
3541
|
+
detail: Object.assign({ newFrame }, options),
|
|
3542
|
+
cancelable: true,
|
|
3543
|
+
});
|
|
3544
|
+
const { defaultPrevented, detail: { render }, } = event;
|
|
3545
|
+
if (this.view.renderer && render) {
|
|
3546
|
+
this.view.renderer.renderElement = render;
|
|
3547
|
+
}
|
|
3548
|
+
return !defaultPrevented;
|
|
3549
|
+
}
|
|
3550
|
+
viewRenderedSnapshot(_snapshot, _isPreview) { }
|
|
3551
|
+
preloadOnLoadLinksForView(element) {
|
|
3552
|
+
session.preloadOnLoadLinksForView(element);
|
|
3553
|
+
}
|
|
3554
|
+
viewInvalidated() { }
|
|
3555
|
+
willRenderFrame(currentElement, _newElement) {
|
|
3556
|
+
this.previousFrameElement = currentElement.cloneNode(true);
|
|
3557
|
+
}
|
|
3558
|
+
async loadFrameResponse(fetchResponse, document) {
|
|
3559
|
+
const newFrameElement = await this.extractForeignFrameElement(document.body);
|
|
3560
|
+
if (newFrameElement) {
|
|
3561
|
+
const snapshot = new Snapshot(newFrameElement);
|
|
3562
|
+
const renderer = new FrameRenderer(this, this.view.snapshot, snapshot, FrameRenderer.renderElement, false, false);
|
|
3563
|
+
if (this.view.renderPromise)
|
|
3564
|
+
await this.view.renderPromise;
|
|
3565
|
+
this.changeHistory();
|
|
3566
|
+
await this.view.render(renderer);
|
|
3567
|
+
this.complete = true;
|
|
3568
|
+
session.frameRendered(fetchResponse, this.element);
|
|
3569
|
+
session.frameLoaded(this.element);
|
|
3570
|
+
this.fetchResponseLoaded(fetchResponse);
|
|
3571
|
+
}
|
|
3572
|
+
else if (this.willHandleFrameMissingFromResponse(fetchResponse)) {
|
|
3573
|
+
this.handleFrameMissingFromResponse(fetchResponse);
|
|
3574
|
+
}
|
|
3015
3575
|
}
|
|
3016
3576
|
async visit(url) {
|
|
3017
3577
|
var _a;
|
|
3018
|
-
const request = new FetchRequest(this, FetchMethod.get, url, new URLSearchParams, this.element);
|
|
3578
|
+
const request = new FetchRequest(this, FetchMethod.get, url, new URLSearchParams(), this.element);
|
|
3019
3579
|
(_a = this.currentFetchRequest) === null || _a === void 0 ? void 0 : _a.cancel();
|
|
3020
3580
|
this.currentFetchRequest = request;
|
|
3021
|
-
return new Promise(resolve => {
|
|
3581
|
+
return new Promise((resolve) => {
|
|
3022
3582
|
this.resolveVisitPromise = () => {
|
|
3023
3583
|
this.resolveVisitPromise = () => { };
|
|
3024
3584
|
this.currentFetchRequest = null;
|
|
@@ -3029,24 +3589,78 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3029
3589
|
}
|
|
3030
3590
|
navigateFrame(element, url, submitter) {
|
|
3031
3591
|
const frame = this.findFrameElement(element, submitter);
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3592
|
+
frame.delegate.proposeVisitIfNavigatedWithAction(frame, element, submitter);
|
|
3593
|
+
this.withCurrentNavigationElement(element, () => {
|
|
3594
|
+
frame.src = url;
|
|
3595
|
+
});
|
|
3035
3596
|
}
|
|
3036
3597
|
proposeVisitIfNavigatedWithAction(frame, element, submitter) {
|
|
3037
|
-
|
|
3038
|
-
if (
|
|
3039
|
-
const
|
|
3598
|
+
this.action = getVisitAction(submitter, element, frame);
|
|
3599
|
+
if (this.action) {
|
|
3600
|
+
const pageSnapshot = PageSnapshot.fromElement(frame).clone();
|
|
3601
|
+
const { visitCachedSnapshot } = frame.delegate;
|
|
3040
3602
|
frame.delegate.fetchResponseLoaded = (fetchResponse) => {
|
|
3041
3603
|
if (frame.src) {
|
|
3042
3604
|
const { statusCode, redirected } = fetchResponse;
|
|
3043
3605
|
const responseHTML = frame.ownerDocument.documentElement.outerHTML;
|
|
3044
3606
|
const response = { statusCode, redirected, responseHTML };
|
|
3045
|
-
|
|
3607
|
+
const options = {
|
|
3608
|
+
response,
|
|
3609
|
+
visitCachedSnapshot,
|
|
3610
|
+
willRender: false,
|
|
3611
|
+
updateHistory: false,
|
|
3612
|
+
restorationIdentifier: this.restorationIdentifier,
|
|
3613
|
+
snapshot: pageSnapshot,
|
|
3614
|
+
};
|
|
3615
|
+
if (this.action)
|
|
3616
|
+
options.action = this.action;
|
|
3617
|
+
session.visit(frame.src, options);
|
|
3046
3618
|
}
|
|
3047
3619
|
};
|
|
3048
3620
|
}
|
|
3049
3621
|
}
|
|
3622
|
+
changeHistory() {
|
|
3623
|
+
if (this.action) {
|
|
3624
|
+
const method = getHistoryMethodForAction(this.action);
|
|
3625
|
+
session.history.update(method, expandURL(this.element.src || ""), this.restorationIdentifier);
|
|
3626
|
+
}
|
|
3627
|
+
}
|
|
3628
|
+
async handleUnvisitableFrameResponse(fetchResponse) {
|
|
3629
|
+
console.warn(`The response (${fetchResponse.statusCode}) from <turbo-frame id="${this.element.id}"> is performing a full page visit due to turbo-visit-control.`);
|
|
3630
|
+
await this.visitResponse(fetchResponse.response);
|
|
3631
|
+
}
|
|
3632
|
+
willHandleFrameMissingFromResponse(fetchResponse) {
|
|
3633
|
+
this.element.setAttribute("complete", "");
|
|
3634
|
+
const response = fetchResponse.response;
|
|
3635
|
+
const visit = async (url, options = {}) => {
|
|
3636
|
+
if (url instanceof Response) {
|
|
3637
|
+
this.visitResponse(url);
|
|
3638
|
+
}
|
|
3639
|
+
else {
|
|
3640
|
+
session.visit(url, options);
|
|
3641
|
+
}
|
|
3642
|
+
};
|
|
3643
|
+
const event = dispatch("turbo:frame-missing", {
|
|
3644
|
+
target: this.element,
|
|
3645
|
+
detail: { response, visit },
|
|
3646
|
+
cancelable: true,
|
|
3647
|
+
});
|
|
3648
|
+
return !event.defaultPrevented;
|
|
3649
|
+
}
|
|
3650
|
+
handleFrameMissingFromResponse(fetchResponse) {
|
|
3651
|
+
this.view.missing();
|
|
3652
|
+
this.throwFrameMissingError(fetchResponse);
|
|
3653
|
+
}
|
|
3654
|
+
throwFrameMissingError(fetchResponse) {
|
|
3655
|
+
const message = `The response (${fetchResponse.statusCode}) did not contain the expected <turbo-frame id="${this.element.id}"> and will be ignored. To perform a full page visit instead, set turbo-visit-control to reload.`;
|
|
3656
|
+
throw new TurboFrameMissingError(message);
|
|
3657
|
+
}
|
|
3658
|
+
async visitResponse(response) {
|
|
3659
|
+
const wrapped = new FetchResponse(response);
|
|
3660
|
+
const responseHTML = await wrapped.responseHTML;
|
|
3661
|
+
const { location, redirected, statusCode } = wrapped;
|
|
3662
|
+
return session.visit(location, { response: { redirected, statusCode, responseHTML } });
|
|
3663
|
+
}
|
|
3050
3664
|
findFrameElement(element, submitter) {
|
|
3051
3665
|
var _a;
|
|
3052
3666
|
const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target");
|
|
@@ -3056,19 +3670,21 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3056
3670
|
let element;
|
|
3057
3671
|
const id = CSS.escape(this.id);
|
|
3058
3672
|
try {
|
|
3059
|
-
|
|
3673
|
+
element = activateElement(container.querySelector(`turbo-frame#${id}`), this.sourceURL);
|
|
3674
|
+
if (element) {
|
|
3060
3675
|
return element;
|
|
3061
3676
|
}
|
|
3062
|
-
|
|
3677
|
+
element = activateElement(container.querySelector(`turbo-frame[src][recurse~=${id}]`), this.sourceURL);
|
|
3678
|
+
if (element) {
|
|
3063
3679
|
await element.loaded;
|
|
3064
3680
|
return await this.extractForeignFrameElement(element);
|
|
3065
3681
|
}
|
|
3066
|
-
console.error(`Response has no matching <turbo-frame id="${id}"> element`);
|
|
3067
3682
|
}
|
|
3068
3683
|
catch (error) {
|
|
3069
3684
|
console.error(error);
|
|
3685
|
+
return new FrameElement();
|
|
3070
3686
|
}
|
|
3071
|
-
return
|
|
3687
|
+
return null;
|
|
3072
3688
|
}
|
|
3073
3689
|
formActionIsVisitable(form, submitter) {
|
|
3074
3690
|
const action = getAction(form, submitter);
|
|
@@ -3088,10 +3704,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3088
3704
|
return !frameElement.disabled;
|
|
3089
3705
|
}
|
|
3090
3706
|
}
|
|
3091
|
-
if (!session.
|
|
3707
|
+
if (!session.elementIsNavigatable(element)) {
|
|
3092
3708
|
return false;
|
|
3093
3709
|
}
|
|
3094
|
-
if (submitter && !session.
|
|
3710
|
+
if (submitter && !session.elementIsNavigatable(submitter)) {
|
|
3095
3711
|
return false;
|
|
3096
3712
|
}
|
|
3097
3713
|
return true;
|
|
@@ -3107,24 +3723,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3107
3723
|
return this.element.src;
|
|
3108
3724
|
}
|
|
3109
3725
|
}
|
|
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
3726
|
set sourceURL(sourceURL) {
|
|
3124
|
-
this.
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
this.settingSourceURL = false;
|
|
3727
|
+
this.ignoringChangesToAttribute("src", () => {
|
|
3728
|
+
this.element.src = sourceURL !== null && sourceURL !== void 0 ? sourceURL : null;
|
|
3729
|
+
});
|
|
3128
3730
|
}
|
|
3129
3731
|
get loadingStyle() {
|
|
3130
3732
|
return this.element.loading;
|
|
@@ -3132,6 +3734,19 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3132
3734
|
get isLoading() {
|
|
3133
3735
|
return this.formSubmission !== undefined || this.resolveVisitPromise() !== undefined;
|
|
3134
3736
|
}
|
|
3737
|
+
get complete() {
|
|
3738
|
+
return this.element.hasAttribute("complete");
|
|
3739
|
+
}
|
|
3740
|
+
set complete(value) {
|
|
3741
|
+
this.ignoringChangesToAttribute("complete", () => {
|
|
3742
|
+
if (value) {
|
|
3743
|
+
this.element.setAttribute("complete", "");
|
|
3744
|
+
}
|
|
3745
|
+
else {
|
|
3746
|
+
this.element.removeAttribute("complete");
|
|
3747
|
+
}
|
|
3748
|
+
});
|
|
3749
|
+
}
|
|
3135
3750
|
get isActive() {
|
|
3136
3751
|
return this.element.isActive && this.connected;
|
|
3137
3752
|
}
|
|
@@ -3141,16 +3756,18 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3141
3756
|
const root = (_a = meta === null || meta === void 0 ? void 0 : meta.content) !== null && _a !== void 0 ? _a : "/";
|
|
3142
3757
|
return expandURL(root);
|
|
3143
3758
|
}
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
this.
|
|
3759
|
+
isIgnoringChangesTo(attributeName) {
|
|
3760
|
+
return this.ignoredAttributes.has(attributeName);
|
|
3761
|
+
}
|
|
3762
|
+
ignoringChangesToAttribute(attributeName, callback) {
|
|
3763
|
+
this.ignoredAttributes.add(attributeName);
|
|
3764
|
+
callback();
|
|
3765
|
+
this.ignoredAttributes.delete(attributeName);
|
|
3766
|
+
}
|
|
3767
|
+
withCurrentNavigationElement(element, callback) {
|
|
3768
|
+
this.currentNavigationElement = element;
|
|
3769
|
+
callback();
|
|
3770
|
+
delete this.currentNavigationElement;
|
|
3154
3771
|
}
|
|
3155
3772
|
}
|
|
3156
3773
|
function getFrameElementById(id) {
|
|
@@ -3178,36 +3795,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3178
3795
|
}
|
|
3179
3796
|
}
|
|
3180
3797
|
|
|
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
3798
|
class StreamElement extends HTMLElement {
|
|
3799
|
+
static async renderElement(newElement) {
|
|
3800
|
+
await newElement.performAction();
|
|
3801
|
+
}
|
|
3211
3802
|
async connectedCallback() {
|
|
3212
3803
|
try {
|
|
3213
3804
|
await this.render();
|
|
@@ -3221,12 +3812,13 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3221
3812
|
}
|
|
3222
3813
|
async render() {
|
|
3223
3814
|
var _a;
|
|
3224
|
-
return (_a = this.renderPromise) !== null && _a !== void 0 ? _a : (this.renderPromise = (async () => {
|
|
3225
|
-
|
|
3815
|
+
return ((_a = this.renderPromise) !== null && _a !== void 0 ? _a : (this.renderPromise = (async () => {
|
|
3816
|
+
const event = this.beforeRenderEvent;
|
|
3817
|
+
if (this.dispatchEvent(event)) {
|
|
3226
3818
|
await nextAnimationFrame();
|
|
3227
|
-
|
|
3819
|
+
await event.detail.render(this);
|
|
3228
3820
|
}
|
|
3229
|
-
})());
|
|
3821
|
+
})()));
|
|
3230
3822
|
}
|
|
3231
3823
|
disconnect() {
|
|
3232
3824
|
try {
|
|
@@ -3235,13 +3827,13 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3235
3827
|
catch (_a) { }
|
|
3236
3828
|
}
|
|
3237
3829
|
removeDuplicateTargetChildren() {
|
|
3238
|
-
this.duplicateChildren.forEach(c => c.remove());
|
|
3830
|
+
this.duplicateChildren.forEach((c) => c.remove());
|
|
3239
3831
|
}
|
|
3240
3832
|
get duplicateChildren() {
|
|
3241
3833
|
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));
|
|
3834
|
+
const existingChildren = this.targetElements.flatMap((e) => [...e.children]).filter((c) => !!c.id);
|
|
3835
|
+
const newChildrenIds = [...(((_a = this.templateContent) === null || _a === void 0 ? void 0 : _a.children) || [])].filter((c) => !!c.id).map((c) => c.id);
|
|
3836
|
+
return existingChildren.filter((c) => newChildrenIds.includes(c.id));
|
|
3245
3837
|
}
|
|
3246
3838
|
get performAction() {
|
|
3247
3839
|
if (this.action) {
|
|
@@ -3268,7 +3860,12 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3268
3860
|
return this.templateElement.content.cloneNode(true);
|
|
3269
3861
|
}
|
|
3270
3862
|
get templateElement() {
|
|
3271
|
-
if (this.firstElementChild
|
|
3863
|
+
if (this.firstElementChild === null) {
|
|
3864
|
+
const template = this.ownerDocument.createElement("template");
|
|
3865
|
+
this.appendChild(template);
|
|
3866
|
+
return template;
|
|
3867
|
+
}
|
|
3868
|
+
else if (this.firstElementChild instanceof HTMLTemplateElement) {
|
|
3272
3869
|
return this.firstElementChild;
|
|
3273
3870
|
}
|
|
3274
3871
|
this.raise("first child element must be a <template> element");
|
|
@@ -3290,7 +3887,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3290
3887
|
return (_b = ((_a = this.outerHTML.match(/<[^>]+>/)) !== null && _a !== void 0 ? _a : [])[0]) !== null && _b !== void 0 ? _b : "<turbo-stream>";
|
|
3291
3888
|
}
|
|
3292
3889
|
get beforeRenderEvent() {
|
|
3293
|
-
return new CustomEvent("turbo:before-stream-render", {
|
|
3890
|
+
return new CustomEvent("turbo:before-stream-render", {
|
|
3891
|
+
bubbles: true,
|
|
3892
|
+
cancelable: true,
|
|
3893
|
+
detail: { newStream: this, render: StreamElement.renderElement },
|
|
3894
|
+
});
|
|
3294
3895
|
}
|
|
3295
3896
|
get targetElementsById() {
|
|
3296
3897
|
var _a;
|
|
@@ -3314,9 +3915,35 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3314
3915
|
}
|
|
3315
3916
|
}
|
|
3316
3917
|
|
|
3918
|
+
class StreamSourceElement extends HTMLElement {
|
|
3919
|
+
constructor() {
|
|
3920
|
+
super(...arguments);
|
|
3921
|
+
this.streamSource = null;
|
|
3922
|
+
}
|
|
3923
|
+
connectedCallback() {
|
|
3924
|
+
this.streamSource = this.src.match(/^ws{1,2}:/) ? new WebSocket(this.src) : new EventSource(this.src);
|
|
3925
|
+
connectStreamSource(this.streamSource);
|
|
3926
|
+
}
|
|
3927
|
+
disconnectedCallback() {
|
|
3928
|
+
if (this.streamSource) {
|
|
3929
|
+
disconnectStreamSource(this.streamSource);
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3932
|
+
get src() {
|
|
3933
|
+
return this.getAttribute("src") || "";
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3317
3937
|
FrameElement.delegateConstructor = FrameController;
|
|
3318
|
-
customElements.
|
|
3319
|
-
|
|
3938
|
+
if (customElements.get("turbo-frame") === undefined) {
|
|
3939
|
+
customElements.define("turbo-frame", FrameElement);
|
|
3940
|
+
}
|
|
3941
|
+
if (customElements.get("turbo-stream") === undefined) {
|
|
3942
|
+
customElements.define("turbo-stream", StreamElement);
|
|
3943
|
+
}
|
|
3944
|
+
if (customElements.get("turbo-stream-source") === undefined) {
|
|
3945
|
+
customElements.define("turbo-stream-source", StreamSourceElement);
|
|
3946
|
+
}
|
|
3320
3947
|
|
|
3321
3948
|
(() => {
|
|
3322
3949
|
let element = document.currentScript;
|
|
@@ -3324,7 +3951,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3324
3951
|
return;
|
|
3325
3952
|
if (element.hasAttribute("data-turbo-suppress-warning"))
|
|
3326
3953
|
return;
|
|
3327
|
-
|
|
3954
|
+
element = element.parentElement;
|
|
3955
|
+
while (element) {
|
|
3328
3956
|
if (element == document.body) {
|
|
3329
3957
|
return console.warn(unindent `
|
|
3330
3958
|
You are loading Turbo from a <script> element inside the <body> element. This is probably not what you meant to do!
|
|
@@ -3337,14 +3965,21 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3337
3965
|
Suppress this warning by adding a "data-turbo-suppress-warning" attribute to: %s
|
|
3338
3966
|
`, element.outerHTML);
|
|
3339
3967
|
}
|
|
3968
|
+
element = element.parentElement;
|
|
3340
3969
|
}
|
|
3341
3970
|
})();
|
|
3342
3971
|
|
|
3343
3972
|
window.Turbo = Turbo;
|
|
3344
3973
|
start();
|
|
3345
3974
|
|
|
3975
|
+
exports.FrameElement = FrameElement;
|
|
3976
|
+
exports.FrameRenderer = FrameRenderer;
|
|
3346
3977
|
exports.PageRenderer = PageRenderer;
|
|
3347
3978
|
exports.PageSnapshot = PageSnapshot;
|
|
3979
|
+
exports.StreamActions = StreamActions;
|
|
3980
|
+
exports.StreamElement = StreamElement;
|
|
3981
|
+
exports.StreamSourceElement = StreamSourceElement;
|
|
3982
|
+
exports.cache = cache;
|
|
3348
3983
|
exports.clearCache = clearCache;
|
|
3349
3984
|
exports.connectStreamSource = connectStreamSource;
|
|
3350
3985
|
exports.disconnectStreamSource = disconnectStreamSource;
|
|
@@ -3353,10 +3988,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3353
3988
|
exports.renderStreamMessage = renderStreamMessage;
|
|
3354
3989
|
exports.session = session;
|
|
3355
3990
|
exports.setConfirmMethod = setConfirmMethod;
|
|
3991
|
+
exports.setFormMode = setFormMode;
|
|
3356
3992
|
exports.setProgressBarDelay = setProgressBarDelay;
|
|
3357
3993
|
exports.start = start;
|
|
3358
3994
|
exports.visit = visit;
|
|
3359
3995
|
|
|
3360
3996
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3361
3997
|
|
|
3362
|
-
}))
|
|
3998
|
+
}));
|