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