@hotwired/turbo 7.0.0-rc.4 → 7.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/README.md +0 -2
- package/dist/turbo.es2017-esm.js +270 -60
- package/dist/turbo.es2017-umd.js +271 -60
- package/dist/types/core/drive/form_submission.d.ts +3 -0
- package/dist/types/core/drive/navigator.d.ts +1 -0
- package/dist/types/core/drive/visit.d.ts +4 -0
- package/dist/types/core/frames/frame_controller.d.ts +7 -3
- package/dist/types/core/frames/frame_redirector.d.ts +1 -0
- package/dist/types/core/index.d.ts +1 -0
- package/dist/types/core/session.d.ts +2 -1
- package/dist/types/core/url.d.ts +2 -0
- package/dist/types/elements/frame_element.d.ts +1 -0
- package/dist/types/polyfills/index.d.ts +1 -0
- package/dist/types/tests/functional/drive_disabled_tests.d.ts +2 -0
- package/dist/types/tests/functional/drive_tests.d.ts +1 -0
- package/dist/types/tests/functional/form_submission_tests.d.ts +29 -3
- package/dist/types/tests/functional/frame_tests.d.ts +14 -1
- package/dist/types/tests/functional/navigation_tests.d.ts +4 -2
- package/dist/types/util.d.ts +3 -0
- package/package.json +7 -2
- package/dist/turbo.es2017-esm.js.map +0 -1
- package/dist/turbo.es2017-umd.js.map +0 -1
- package/dist/turbo.es5-umd.js +0 -3954
- package/dist/turbo.es5-umd.js.map +0 -1
package/dist/turbo.es2017-umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Turbo 7.0.
|
|
2
|
+
Turbo 7.0.1
|
|
3
3
|
Copyright © 2021 Basecamp, LLC
|
|
4
4
|
*/
|
|
5
5
|
(function (global, factory) {
|
|
@@ -26,6 +26,58 @@ Copyright © 2021 Basecamp, LLC
|
|
|
26
26
|
Object.setPrototypeOf(HTMLElement, BuiltInHTMLElement);
|
|
27
27
|
})();
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* The MIT License (MIT)
|
|
31
|
+
*
|
|
32
|
+
* Copyright (c) 2019 Javan Makhmali
|
|
33
|
+
*
|
|
34
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
35
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
36
|
+
* in the Software without restriction, including without limitation the rights
|
|
37
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
38
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
39
|
+
* furnished to do so, subject to the following conditions:
|
|
40
|
+
*
|
|
41
|
+
* The above copyright notice and this permission notice shall be included in
|
|
42
|
+
* all copies or substantial portions of the Software.
|
|
43
|
+
*
|
|
44
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
45
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
46
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
47
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
48
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
49
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
50
|
+
* THE SOFTWARE.
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
(function(prototype) {
|
|
54
|
+
if (typeof prototype.requestSubmit == "function") return
|
|
55
|
+
|
|
56
|
+
prototype.requestSubmit = function(submitter) {
|
|
57
|
+
if (submitter) {
|
|
58
|
+
validateSubmitter(submitter, this);
|
|
59
|
+
submitter.click();
|
|
60
|
+
} else {
|
|
61
|
+
submitter = document.createElement("input");
|
|
62
|
+
submitter.type = "submit";
|
|
63
|
+
submitter.hidden = true;
|
|
64
|
+
this.appendChild(submitter);
|
|
65
|
+
submitter.click();
|
|
66
|
+
this.removeChild(submitter);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
function validateSubmitter(submitter, form) {
|
|
71
|
+
submitter instanceof HTMLElement || raise(TypeError, "parameter 1 is not of type 'HTMLElement'");
|
|
72
|
+
submitter.type == "submit" || raise(TypeError, "The specified element is not a submit button");
|
|
73
|
+
submitter.form == form || raise(DOMException, "The specified element is not owned by this form element", "NotFoundError");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function raise(errorConstructor, message, name) {
|
|
77
|
+
throw new errorConstructor("Failed to execute 'requestSubmit' on 'HTMLFormElement': " + message + ".", name)
|
|
78
|
+
}
|
|
79
|
+
})(HTMLFormElement.prototype);
|
|
80
|
+
|
|
29
81
|
const submittersByForm = new WeakMap;
|
|
30
82
|
function findSubmitterFromClickTarget(target) {
|
|
31
83
|
const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
|
|
@@ -39,12 +91,20 @@ Copyright © 2021 Basecamp, LLC
|
|
|
39
91
|
}
|
|
40
92
|
}
|
|
41
93
|
(function () {
|
|
42
|
-
if ("SubmitEvent" in window)
|
|
43
|
-
return;
|
|
44
94
|
if ("submitter" in Event.prototype)
|
|
45
95
|
return;
|
|
96
|
+
let prototype;
|
|
97
|
+
if ("SubmitEvent" in window && /Apple Computer/.test(navigator.vendor)) {
|
|
98
|
+
prototype = window.SubmitEvent.prototype;
|
|
99
|
+
}
|
|
100
|
+
else if ("SubmitEvent" in window) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
prototype = window.Event.prototype;
|
|
105
|
+
}
|
|
46
106
|
addEventListener("click", clickCaptured, true);
|
|
47
|
-
Object.defineProperty(
|
|
107
|
+
Object.defineProperty(prototype, "submitter", {
|
|
48
108
|
get() {
|
|
49
109
|
if (this.type == "submit" && this.target instanceof HTMLFormElement) {
|
|
50
110
|
return submittersByForm.get(this.target);
|
|
@@ -163,6 +223,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
163
223
|
return anchorMatch[1];
|
|
164
224
|
}
|
|
165
225
|
}
|
|
226
|
+
function getAction(form, submitter) {
|
|
227
|
+
const action = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formaction")) || form.getAttribute("action") || form.action;
|
|
228
|
+
return expandURL(action);
|
|
229
|
+
}
|
|
166
230
|
function getExtension(url) {
|
|
167
231
|
return (getLastPathComponent(url).match(/\.[^.]*$/) || [])[0] || "";
|
|
168
232
|
}
|
|
@@ -173,6 +237,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
173
237
|
const prefix = getPrefix(url);
|
|
174
238
|
return baseURL.href === expandURL(prefix).href || baseURL.href.startsWith(prefix);
|
|
175
239
|
}
|
|
240
|
+
function locationIsVisitable(location, rootLocation) {
|
|
241
|
+
return isPrefixedBy(location, rootLocation) && isHTML(location);
|
|
242
|
+
}
|
|
176
243
|
function getRequestURL(url) {
|
|
177
244
|
const anchor = getAnchor(url);
|
|
178
245
|
return anchor != null
|
|
@@ -247,7 +314,12 @@ Copyright © 2021 Basecamp, LLC
|
|
|
247
314
|
|
|
248
315
|
function dispatch(eventName, { target, cancelable, detail } = {}) {
|
|
249
316
|
const event = new CustomEvent(eventName, { cancelable, bubbles: true, detail });
|
|
250
|
-
|
|
317
|
+
if (target && target.isConnected) {
|
|
318
|
+
target.dispatchEvent(event);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
document.documentElement.dispatchEvent(event);
|
|
322
|
+
}
|
|
251
323
|
return event;
|
|
252
324
|
}
|
|
253
325
|
function nextAnimationFrame() {
|
|
@@ -290,6 +362,29 @@ Copyright © 2021 Basecamp, LLC
|
|
|
290
362
|
}
|
|
291
363
|
}).join("");
|
|
292
364
|
}
|
|
365
|
+
function getAttribute(attributeName, ...elements) {
|
|
366
|
+
for (const value of elements.map(element => element === null || element === void 0 ? void 0 : element.getAttribute(attributeName))) {
|
|
367
|
+
if (typeof value == "string")
|
|
368
|
+
return value;
|
|
369
|
+
}
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
function markAsBusy(...elements) {
|
|
373
|
+
for (const element of elements) {
|
|
374
|
+
if (element.localName == "turbo-frame") {
|
|
375
|
+
element.setAttribute("busy", "");
|
|
376
|
+
}
|
|
377
|
+
element.setAttribute("aria-busy", "true");
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
function clearBusyState(...elements) {
|
|
381
|
+
for (const element of elements) {
|
|
382
|
+
if (element.localName == "turbo-frame") {
|
|
383
|
+
element.removeAttribute("busy");
|
|
384
|
+
}
|
|
385
|
+
element.removeAttribute("aria-busy");
|
|
386
|
+
}
|
|
387
|
+
}
|
|
293
388
|
|
|
294
389
|
var FetchMethod;
|
|
295
390
|
(function (FetchMethod) {
|
|
@@ -519,6 +614,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
519
614
|
this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
|
|
520
615
|
this.mustRedirect = mustRedirect;
|
|
521
616
|
}
|
|
617
|
+
static confirmMethod(message, element) {
|
|
618
|
+
return confirm(message);
|
|
619
|
+
}
|
|
522
620
|
get method() {
|
|
523
621
|
var _a;
|
|
524
622
|
const method = ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formmethod")) || this.formElement.getAttribute("method") || "";
|
|
@@ -552,8 +650,20 @@ Copyright © 2021 Basecamp, LLC
|
|
|
552
650
|
return entries.concat(typeof value == "string" ? [[name, value]] : []);
|
|
553
651
|
}, []);
|
|
554
652
|
}
|
|
653
|
+
get confirmationMessage() {
|
|
654
|
+
return this.formElement.getAttribute("data-turbo-confirm");
|
|
655
|
+
}
|
|
656
|
+
get needsConfirmation() {
|
|
657
|
+
return this.confirmationMessage !== null;
|
|
658
|
+
}
|
|
555
659
|
async start() {
|
|
556
660
|
const { initialized, requesting } = FormSubmissionState;
|
|
661
|
+
if (this.needsConfirmation) {
|
|
662
|
+
const answer = FormSubmission.confirmMethod(this.confirmationMessage, this.formElement);
|
|
663
|
+
if (!answer) {
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
557
667
|
if (this.state == initialized) {
|
|
558
668
|
this.state = requesting;
|
|
559
669
|
return this.fetchRequest.perform();
|
|
@@ -577,7 +687,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
577
687
|
}
|
|
578
688
|
}
|
|
579
689
|
requestStarted(request) {
|
|
690
|
+
var _a;
|
|
580
691
|
this.state = FormSubmissionState.waiting;
|
|
692
|
+
(_a = this.submitter) === null || _a === void 0 ? void 0 : _a.setAttribute("disabled", "");
|
|
581
693
|
dispatch("turbo:submit-start", { target: this.formElement, detail: { formSubmission: this } });
|
|
582
694
|
this.delegate.formSubmissionStarted(this);
|
|
583
695
|
}
|
|
@@ -607,7 +719,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
607
719
|
this.delegate.formSubmissionErrored(this, error);
|
|
608
720
|
}
|
|
609
721
|
requestFinished(request) {
|
|
722
|
+
var _a;
|
|
610
723
|
this.state = FormSubmissionState.stopped;
|
|
724
|
+
(_a = this.submitter) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled");
|
|
611
725
|
dispatch("turbo:submit-end", { target: this.formElement, detail: Object.assign({ formSubmission: this }, this.result) });
|
|
612
726
|
this.delegate.formSubmissionFinished(this);
|
|
613
727
|
}
|
|
@@ -683,10 +797,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
683
797
|
class FormInterceptor {
|
|
684
798
|
constructor(delegate, element) {
|
|
685
799
|
this.submitBubbled = ((event) => {
|
|
686
|
-
|
|
687
|
-
|
|
800
|
+
const form = event.target;
|
|
801
|
+
if (form instanceof HTMLFormElement && form.closest("turbo-frame, html") == this.element) {
|
|
688
802
|
const submitter = event.submitter || undefined;
|
|
689
|
-
|
|
803
|
+
const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.method;
|
|
804
|
+
if (method != "dialog" && this.delegate.shouldInterceptFormSubmission(form, submitter)) {
|
|
690
805
|
event.preventDefault();
|
|
691
806
|
event.stopImmediatePropagation();
|
|
692
807
|
this.delegate.formSubmissionIntercepted(form, submitter);
|
|
@@ -1280,7 +1395,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1280
1395
|
})(VisitState || (VisitState = {}));
|
|
1281
1396
|
const defaultOptions = {
|
|
1282
1397
|
action: "advance",
|
|
1283
|
-
|
|
1398
|
+
delegate: {},
|
|
1399
|
+
historyChanged: false,
|
|
1284
1400
|
};
|
|
1285
1401
|
var SystemStatusCode;
|
|
1286
1402
|
(function (SystemStatusCode) {
|
|
@@ -1300,13 +1416,14 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1300
1416
|
this.delegate = delegate;
|
|
1301
1417
|
this.location = location;
|
|
1302
1418
|
this.restorationIdentifier = restorationIdentifier || uuid();
|
|
1303
|
-
const { action, historyChanged, referrer, snapshotHTML, response } = Object.assign(Object.assign({}, defaultOptions), options);
|
|
1419
|
+
const { action, historyChanged, referrer, snapshotHTML, response, delegate: optionalDelegate } = Object.assign(Object.assign({}, defaultOptions), options);
|
|
1304
1420
|
this.action = action;
|
|
1305
1421
|
this.historyChanged = historyChanged;
|
|
1306
1422
|
this.referrer = referrer;
|
|
1307
1423
|
this.snapshotHTML = snapshotHTML;
|
|
1308
1424
|
this.response = response;
|
|
1309
1425
|
this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action);
|
|
1426
|
+
this.optionalDelegate = optionalDelegate;
|
|
1310
1427
|
}
|
|
1311
1428
|
get adapter() {
|
|
1312
1429
|
return this.delegate.adapter;
|
|
@@ -1329,6 +1446,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1329
1446
|
this.state = VisitState.started;
|
|
1330
1447
|
this.adapter.visitStarted(this);
|
|
1331
1448
|
this.delegate.visitStarted(this);
|
|
1449
|
+
if (this.optionalDelegate.visitStarted)
|
|
1450
|
+
this.optionalDelegate.visitStarted(this);
|
|
1332
1451
|
}
|
|
1333
1452
|
}
|
|
1334
1453
|
cancel() {
|
|
@@ -1458,7 +1577,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1458
1577
|
}
|
|
1459
1578
|
}
|
|
1460
1579
|
followRedirect() {
|
|
1461
|
-
|
|
1580
|
+
var _a;
|
|
1581
|
+
if (this.redirectedToLocation && !this.followedRedirect && ((_a = this.response) === null || _a === void 0 ? void 0 : _a.redirected)) {
|
|
1462
1582
|
this.adapter.visitProposedToLocation(this.redirectedToLocation, {
|
|
1463
1583
|
action: 'replace',
|
|
1464
1584
|
response: this.response
|
|
@@ -1481,25 +1601,27 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1481
1601
|
}
|
|
1482
1602
|
async requestSucceededWithResponse(request, response) {
|
|
1483
1603
|
const responseHTML = await response.responseHTML;
|
|
1604
|
+
const { redirected, statusCode } = response;
|
|
1484
1605
|
if (responseHTML == undefined) {
|
|
1485
|
-
this.recordResponse({ statusCode: SystemStatusCode.contentTypeMismatch });
|
|
1606
|
+
this.recordResponse({ statusCode: SystemStatusCode.contentTypeMismatch, redirected });
|
|
1486
1607
|
}
|
|
1487
1608
|
else {
|
|
1488
1609
|
this.redirectedToLocation = response.redirected ? response.location : undefined;
|
|
1489
|
-
this.recordResponse({ statusCode:
|
|
1610
|
+
this.recordResponse({ statusCode: statusCode, responseHTML, redirected });
|
|
1490
1611
|
}
|
|
1491
1612
|
}
|
|
1492
1613
|
async requestFailedWithResponse(request, response) {
|
|
1493
1614
|
const responseHTML = await response.responseHTML;
|
|
1615
|
+
const { redirected, statusCode } = response;
|
|
1494
1616
|
if (responseHTML == undefined) {
|
|
1495
|
-
this.recordResponse({ statusCode: SystemStatusCode.contentTypeMismatch });
|
|
1617
|
+
this.recordResponse({ statusCode: SystemStatusCode.contentTypeMismatch, redirected });
|
|
1496
1618
|
}
|
|
1497
1619
|
else {
|
|
1498
|
-
this.recordResponse({ statusCode:
|
|
1620
|
+
this.recordResponse({ statusCode: statusCode, responseHTML, redirected });
|
|
1499
1621
|
}
|
|
1500
1622
|
}
|
|
1501
1623
|
requestErrored(request, error) {
|
|
1502
|
-
this.recordResponse({ statusCode: SystemStatusCode.networkFailure });
|
|
1624
|
+
this.recordResponse({ statusCode: SystemStatusCode.networkFailure, redirected: false });
|
|
1503
1625
|
}
|
|
1504
1626
|
requestFinished() {
|
|
1505
1627
|
this.finishRequest();
|
|
@@ -1563,6 +1685,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1563
1685
|
if (!this.snapshotCached) {
|
|
1564
1686
|
this.view.cacheSnapshot();
|
|
1565
1687
|
this.snapshotCached = true;
|
|
1688
|
+
if (this.optionalDelegate.visitCachedSnapshot)
|
|
1689
|
+
this.optionalDelegate.visitCachedSnapshot(this);
|
|
1566
1690
|
}
|
|
1567
1691
|
}
|
|
1568
1692
|
async render(callback) {
|
|
@@ -1711,7 +1835,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1711
1835
|
const form = event.target instanceof HTMLFormElement ? event.target : undefined;
|
|
1712
1836
|
const submitter = event.submitter || undefined;
|
|
1713
1837
|
if (form) {
|
|
1714
|
-
const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.method;
|
|
1838
|
+
const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.getAttribute("method");
|
|
1715
1839
|
if (method != "dialog" && this.delegate.willSubmitForm(form, submitter)) {
|
|
1716
1840
|
event.preventDefault();
|
|
1717
1841
|
this.delegate.formSubmitted(form, submitter);
|
|
@@ -1755,12 +1879,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1755
1879
|
linkClickIntercepted(element, url) {
|
|
1756
1880
|
const frame = this.findFrameElement(element);
|
|
1757
1881
|
if (frame) {
|
|
1758
|
-
frame.
|
|
1759
|
-
frame.src = url;
|
|
1882
|
+
frame.delegate.linkClickIntercepted(element, url);
|
|
1760
1883
|
}
|
|
1761
1884
|
}
|
|
1762
1885
|
shouldInterceptFormSubmission(element, submitter) {
|
|
1763
|
-
return this.
|
|
1886
|
+
return this.shouldSubmit(element, submitter);
|
|
1764
1887
|
}
|
|
1765
1888
|
formSubmissionIntercepted(element, submitter) {
|
|
1766
1889
|
const frame = this.findFrameElement(element, submitter);
|
|
@@ -1769,6 +1892,13 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1769
1892
|
frame.delegate.formSubmissionIntercepted(element, submitter);
|
|
1770
1893
|
}
|
|
1771
1894
|
}
|
|
1895
|
+
shouldSubmit(form, submitter) {
|
|
1896
|
+
var _a;
|
|
1897
|
+
const action = getAction(form, submitter);
|
|
1898
|
+
const meta = this.element.ownerDocument.querySelector(`meta[name="turbo-root"]`);
|
|
1899
|
+
const rootLocation = expandURL((_a = meta === null || meta === void 0 ? void 0 : meta.content) !== null && _a !== void 0 ? _a : "/");
|
|
1900
|
+
return this.shouldRedirect(form, submitter) && locationIsVisitable(action, rootLocation);
|
|
1901
|
+
}
|
|
1772
1902
|
shouldRedirect(element, submitter) {
|
|
1773
1903
|
const frame = this.findFrameElement(element, submitter);
|
|
1774
1904
|
return frame ? frame != element.closest("turbo-frame") : false;
|
|
@@ -1926,7 +2056,12 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1926
2056
|
}
|
|
1927
2057
|
proposeVisit(location, options = {}) {
|
|
1928
2058
|
if (this.delegate.allowsVisitingLocationWithAction(location, options.action)) {
|
|
1929
|
-
|
|
2059
|
+
if (locationIsVisitable(location, this.view.snapshot.rootLocation)) {
|
|
2060
|
+
this.delegate.visitProposedToLocation(location, options);
|
|
2061
|
+
}
|
|
2062
|
+
else {
|
|
2063
|
+
window.location.href = location.toString();
|
|
2064
|
+
}
|
|
1930
2065
|
}
|
|
1931
2066
|
}
|
|
1932
2067
|
startVisit(locatable, restorationIdentifier, options = {}) {
|
|
@@ -1937,12 +2072,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1937
2072
|
submitForm(form, submitter) {
|
|
1938
2073
|
this.stop();
|
|
1939
2074
|
this.formSubmission = new FormSubmission(this, form, submitter, true);
|
|
1940
|
-
|
|
1941
|
-
this.proposeVisit(this.formSubmission.fetchRequest.url, { action: this.getActionForFormSubmission(this.formSubmission) });
|
|
1942
|
-
}
|
|
1943
|
-
else {
|
|
1944
|
-
this.formSubmission.start();
|
|
1945
|
-
}
|
|
2075
|
+
this.formSubmission.start();
|
|
1946
2076
|
}
|
|
1947
2077
|
stop() {
|
|
1948
2078
|
if (this.formSubmission) {
|
|
@@ -1975,8 +2105,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
1975
2105
|
if (formSubmission.method != FetchMethod.get) {
|
|
1976
2106
|
this.view.clearSnapshotCache();
|
|
1977
2107
|
}
|
|
1978
|
-
const { statusCode } = fetchResponse;
|
|
1979
|
-
const
|
|
2108
|
+
const { statusCode, redirected } = fetchResponse;
|
|
2109
|
+
const action = this.getActionForFormSubmission(formSubmission);
|
|
2110
|
+
const visitOptions = { action, response: { statusCode, responseHTML, redirected } };
|
|
1980
2111
|
this.proposeVisit(fetchResponse.location, visitOptions);
|
|
1981
2112
|
}
|
|
1982
2113
|
}
|
|
@@ -2009,6 +2140,9 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2009
2140
|
visitCompleted(visit) {
|
|
2010
2141
|
this.delegate.visitCompleted(visit);
|
|
2011
2142
|
}
|
|
2143
|
+
visitCachedSnapshot(visit) {
|
|
2144
|
+
this.delegate.visitCachedSnapshot(visit);
|
|
2145
|
+
}
|
|
2012
2146
|
locationWithActionIsSamePage(location, action) {
|
|
2013
2147
|
const anchor = getAnchor(location);
|
|
2014
2148
|
const currentAnchor = getAnchor(this.view.lastRenderedLocation);
|
|
@@ -2028,7 +2162,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2028
2162
|
}
|
|
2029
2163
|
getActionForFormSubmission(formSubmission) {
|
|
2030
2164
|
const { formElement, submitter } = formSubmission;
|
|
2031
|
-
const action =
|
|
2165
|
+
const action = getAttribute("data-turbo-action", submitter, formElement);
|
|
2032
2166
|
return isAction(action) ? action : "advance";
|
|
2033
2167
|
}
|
|
2034
2168
|
}
|
|
@@ -2478,7 +2612,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2478
2612
|
}
|
|
2479
2613
|
willFollowLinkToLocation(link, location) {
|
|
2480
2614
|
return this.elementDriveEnabled(link)
|
|
2481
|
-
&&
|
|
2615
|
+
&& locationIsVisitable(location, this.snapshot.rootLocation)
|
|
2482
2616
|
&& this.applicationAllowsFollowingLinkToLocation(link, location);
|
|
2483
2617
|
}
|
|
2484
2618
|
followedLinkToLocation(link, location) {
|
|
@@ -2486,13 +2620,24 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2486
2620
|
this.convertLinkWithMethodClickToFormSubmission(link) || this.visit(location.href, { action });
|
|
2487
2621
|
}
|
|
2488
2622
|
convertLinkWithMethodClickToFormSubmission(link) {
|
|
2489
|
-
var _a;
|
|
2490
2623
|
const linkMethod = link.getAttribute("data-turbo-method");
|
|
2491
2624
|
if (linkMethod) {
|
|
2492
2625
|
const form = document.createElement("form");
|
|
2493
2626
|
form.method = linkMethod;
|
|
2494
2627
|
form.action = link.getAttribute("href") || "undefined";
|
|
2495
|
-
|
|
2628
|
+
form.hidden = true;
|
|
2629
|
+
if (link.hasAttribute("data-turbo-confirm")) {
|
|
2630
|
+
form.setAttribute("data-turbo-confirm", link.getAttribute("data-turbo-confirm"));
|
|
2631
|
+
}
|
|
2632
|
+
const frame = this.getTargetFrameForLink(link);
|
|
2633
|
+
if (frame) {
|
|
2634
|
+
form.setAttribute("data-turbo-frame", frame);
|
|
2635
|
+
form.addEventListener("turbo:submit-start", () => form.remove());
|
|
2636
|
+
}
|
|
2637
|
+
else {
|
|
2638
|
+
form.addEventListener("submit", () => form.remove());
|
|
2639
|
+
}
|
|
2640
|
+
document.body.appendChild(form);
|
|
2496
2641
|
return dispatch("submit", { cancelable: true, target: form });
|
|
2497
2642
|
}
|
|
2498
2643
|
else {
|
|
@@ -2515,6 +2660,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2515
2660
|
visitCompleted(visit) {
|
|
2516
2661
|
this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());
|
|
2517
2662
|
}
|
|
2663
|
+
visitCachedSnapshot(visit) {
|
|
2664
|
+
}
|
|
2518
2665
|
locationWithActionIsSamePage(location, action) {
|
|
2519
2666
|
return this.navigator.locationWithActionIsSamePage(location, action);
|
|
2520
2667
|
}
|
|
@@ -2522,7 +2669,10 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2522
2669
|
this.notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL);
|
|
2523
2670
|
}
|
|
2524
2671
|
willSubmitForm(form, submitter) {
|
|
2525
|
-
|
|
2672
|
+
const action = getAction(form, submitter);
|
|
2673
|
+
return this.elementDriveEnabled(form)
|
|
2674
|
+
&& (!submitter || this.elementDriveEnabled(submitter))
|
|
2675
|
+
&& locationIsVisitable(expandURL(action), this.snapshot.rootLocation);
|
|
2526
2676
|
}
|
|
2527
2677
|
formSubmitted(form, submitter) {
|
|
2528
2678
|
this.navigator.submitForm(form, submitter);
|
|
@@ -2578,6 +2728,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2578
2728
|
return dispatch("turbo:before-visit", { detail: { url: location.href }, cancelable: true });
|
|
2579
2729
|
}
|
|
2580
2730
|
notifyApplicationAfterVisitingLocation(location, action) {
|
|
2731
|
+
markAsBusy(document.documentElement);
|
|
2581
2732
|
return dispatch("turbo:visit", { detail: { url: location.href, action } });
|
|
2582
2733
|
}
|
|
2583
2734
|
notifyApplicationBeforeCachingSnapshot() {
|
|
@@ -2590,6 +2741,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2590
2741
|
return dispatch("turbo:render");
|
|
2591
2742
|
}
|
|
2592
2743
|
notifyApplicationAfterPageLoad(timing = {}) {
|
|
2744
|
+
clearBusyState(document.documentElement);
|
|
2593
2745
|
return dispatch("turbo:load", { detail: { url: this.location.href, timing } });
|
|
2594
2746
|
}
|
|
2595
2747
|
notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL) {
|
|
@@ -2624,8 +2776,17 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2624
2776
|
const action = link.getAttribute("data-turbo-action");
|
|
2625
2777
|
return isAction(action) ? action : "advance";
|
|
2626
2778
|
}
|
|
2627
|
-
|
|
2628
|
-
|
|
2779
|
+
getTargetFrameForLink(link) {
|
|
2780
|
+
const frame = link.getAttribute("data-turbo-frame");
|
|
2781
|
+
if (frame) {
|
|
2782
|
+
return frame;
|
|
2783
|
+
}
|
|
2784
|
+
else {
|
|
2785
|
+
const container = link.closest("turbo-frame");
|
|
2786
|
+
if (container) {
|
|
2787
|
+
return container.id;
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2629
2790
|
}
|
|
2630
2791
|
get snapshot() {
|
|
2631
2792
|
return this.view.snapshot;
|
|
@@ -2643,7 +2804,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2643
2804
|
};
|
|
2644
2805
|
|
|
2645
2806
|
const session = new Session;
|
|
2646
|
-
const { navigator } = session;
|
|
2807
|
+
const { navigator: navigator$1 } = session;
|
|
2647
2808
|
function start() {
|
|
2648
2809
|
session.start();
|
|
2649
2810
|
}
|
|
@@ -2668,10 +2829,13 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2668
2829
|
function setProgressBarDelay(delay) {
|
|
2669
2830
|
session.setProgressBarDelay(delay);
|
|
2670
2831
|
}
|
|
2832
|
+
function setConfirmMethod(confirmMethod) {
|
|
2833
|
+
FormSubmission.confirmMethod = confirmMethod;
|
|
2834
|
+
}
|
|
2671
2835
|
|
|
2672
2836
|
var Turbo = /*#__PURE__*/Object.freeze({
|
|
2673
2837
|
__proto__: null,
|
|
2674
|
-
navigator: navigator,
|
|
2838
|
+
navigator: navigator$1,
|
|
2675
2839
|
session: session,
|
|
2676
2840
|
PageRenderer: PageRenderer,
|
|
2677
2841
|
PageSnapshot: PageSnapshot,
|
|
@@ -2682,11 +2846,13 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2682
2846
|
disconnectStreamSource: disconnectStreamSource,
|
|
2683
2847
|
renderStreamMessage: renderStreamMessage,
|
|
2684
2848
|
clearCache: clearCache,
|
|
2685
|
-
setProgressBarDelay: setProgressBarDelay
|
|
2849
|
+
setProgressBarDelay: setProgressBarDelay,
|
|
2850
|
+
setConfirmMethod: setConfirmMethod
|
|
2686
2851
|
});
|
|
2687
2852
|
|
|
2688
2853
|
class FrameController {
|
|
2689
2854
|
constructor(element) {
|
|
2855
|
+
this.currentFetchRequest = null;
|
|
2690
2856
|
this.resolveVisitPromise = () => { };
|
|
2691
2857
|
this.connected = false;
|
|
2692
2858
|
this.hasBeenLoaded = false;
|
|
@@ -2746,7 +2912,6 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2746
2912
|
this.appearanceObserver.stop();
|
|
2747
2913
|
await this.element.loaded;
|
|
2748
2914
|
this.hasBeenLoaded = true;
|
|
2749
|
-
session.frameLoaded(this.element);
|
|
2750
2915
|
}
|
|
2751
2916
|
catch (error) {
|
|
2752
2917
|
this.currentURL = previousURL;
|
|
@@ -2769,6 +2934,7 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2769
2934
|
await this.view.renderPromise;
|
|
2770
2935
|
await this.view.render(renderer);
|
|
2771
2936
|
session.frameRendered(fetchResponse, this.element);
|
|
2937
|
+
session.frameLoaded(this.element);
|
|
2772
2938
|
}
|
|
2773
2939
|
}
|
|
2774
2940
|
catch (error) {
|
|
@@ -2800,20 +2966,15 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2800
2966
|
}
|
|
2801
2967
|
this.reloadable = false;
|
|
2802
2968
|
this.formSubmission = new FormSubmission(this, element, submitter);
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
else {
|
|
2807
|
-
const { fetchRequest } = this.formSubmission;
|
|
2808
|
-
this.prepareHeadersForRequest(fetchRequest.headers, fetchRequest);
|
|
2809
|
-
this.formSubmission.start();
|
|
2810
|
-
}
|
|
2969
|
+
const { fetchRequest } = this.formSubmission;
|
|
2970
|
+
this.prepareHeadersForRequest(fetchRequest.headers, fetchRequest);
|
|
2971
|
+
this.formSubmission.start();
|
|
2811
2972
|
}
|
|
2812
2973
|
prepareHeadersForRequest(headers, request) {
|
|
2813
2974
|
headers["Turbo-Frame"] = this.id;
|
|
2814
2975
|
}
|
|
2815
2976
|
requestStarted(request) {
|
|
2816
|
-
this.element
|
|
2977
|
+
markAsBusy(this.element);
|
|
2817
2978
|
}
|
|
2818
2979
|
requestPreventedHandlingResponse(request, response) {
|
|
2819
2980
|
this.resolveVisitPromise();
|
|
@@ -2831,14 +2992,14 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2831
2992
|
this.resolveVisitPromise();
|
|
2832
2993
|
}
|
|
2833
2994
|
requestFinished(request) {
|
|
2834
|
-
this.element
|
|
2995
|
+
clearBusyState(this.element);
|
|
2835
2996
|
}
|
|
2836
|
-
formSubmissionStarted(
|
|
2837
|
-
|
|
2838
|
-
frame.setAttribute("busy", "");
|
|
2997
|
+
formSubmissionStarted({ formElement }) {
|
|
2998
|
+
markAsBusy(formElement, this.findFrameElement(formElement));
|
|
2839
2999
|
}
|
|
2840
3000
|
formSubmissionSucceededWithResponse(formSubmission, response) {
|
|
2841
3001
|
const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter);
|
|
3002
|
+
this.proposeVisitIfNavigatedWithAction(frame, formSubmission.formElement, formSubmission.submitter);
|
|
2842
3003
|
frame.delegate.loadResponse(response);
|
|
2843
3004
|
}
|
|
2844
3005
|
formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
|
|
@@ -2847,9 +3008,8 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2847
3008
|
formSubmissionErrored(formSubmission, error) {
|
|
2848
3009
|
console.error(error);
|
|
2849
3010
|
}
|
|
2850
|
-
formSubmissionFinished(
|
|
2851
|
-
|
|
2852
|
-
frame.removeAttribute("busy");
|
|
3011
|
+
formSubmissionFinished({ formElement }) {
|
|
3012
|
+
clearBusyState(formElement, this.findFrameElement(formElement));
|
|
2853
3013
|
}
|
|
2854
3014
|
allowsImmediateRender(snapshot, resume) {
|
|
2855
3015
|
return true;
|
|
@@ -2859,10 +3019,14 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2859
3019
|
viewInvalidated() {
|
|
2860
3020
|
}
|
|
2861
3021
|
async visit(url) {
|
|
2862
|
-
|
|
3022
|
+
var _a;
|
|
3023
|
+
const request = new FetchRequest(this, FetchMethod.get, expandURL(url), new URLSearchParams, this.element);
|
|
3024
|
+
(_a = this.currentFetchRequest) === null || _a === void 0 ? void 0 : _a.cancel();
|
|
3025
|
+
this.currentFetchRequest = request;
|
|
2863
3026
|
return new Promise(resolve => {
|
|
2864
3027
|
this.resolveVisitPromise = () => {
|
|
2865
3028
|
this.resolveVisitPromise = () => { };
|
|
3029
|
+
this.currentFetchRequest = null;
|
|
2866
3030
|
resolve();
|
|
2867
3031
|
};
|
|
2868
3032
|
request.perform();
|
|
@@ -2870,12 +3034,29 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2870
3034
|
}
|
|
2871
3035
|
navigateFrame(element, url, submitter) {
|
|
2872
3036
|
const frame = this.findFrameElement(element, submitter);
|
|
3037
|
+
this.proposeVisitIfNavigatedWithAction(frame, element, submitter);
|
|
2873
3038
|
frame.setAttribute("reloadable", "");
|
|
2874
3039
|
frame.src = url;
|
|
2875
3040
|
}
|
|
3041
|
+
proposeVisitIfNavigatedWithAction(frame, element, submitter) {
|
|
3042
|
+
const action = getAttribute("data-turbo-action", submitter, element, frame);
|
|
3043
|
+
if (isAction(action)) {
|
|
3044
|
+
const delegate = new SnapshotSubstitution(frame);
|
|
3045
|
+
const proposeVisit = (event) => {
|
|
3046
|
+
const { target, detail: { fetchResponse } } = event;
|
|
3047
|
+
if (target instanceof FrameElement && target.src) {
|
|
3048
|
+
const { statusCode, redirected } = fetchResponse;
|
|
3049
|
+
const responseHTML = target.ownerDocument.documentElement.outerHTML;
|
|
3050
|
+
const response = { statusCode, redirected, responseHTML };
|
|
3051
|
+
session.visit(target.src, { action, response, delegate });
|
|
3052
|
+
}
|
|
3053
|
+
};
|
|
3054
|
+
frame.addEventListener("turbo:frame-render", proposeVisit, { once: true });
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
2876
3057
|
findFrameElement(element, submitter) {
|
|
2877
3058
|
var _a;
|
|
2878
|
-
const id =
|
|
3059
|
+
const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target");
|
|
2879
3060
|
return (_a = getFrameElementById(id)) !== null && _a !== void 0 ? _a : this.element;
|
|
2880
3061
|
}
|
|
2881
3062
|
async extractForeignFrameElement(container) {
|
|
@@ -2896,8 +3077,15 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2896
3077
|
}
|
|
2897
3078
|
return new FrameElement();
|
|
2898
3079
|
}
|
|
3080
|
+
formActionIsVisitable(form, submitter) {
|
|
3081
|
+
const action = getAction(form, submitter);
|
|
3082
|
+
return locationIsVisitable(expandURL(action), this.rootLocation);
|
|
3083
|
+
}
|
|
2899
3084
|
shouldInterceptNavigation(element, submitter) {
|
|
2900
|
-
const id =
|
|
3085
|
+
const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target");
|
|
3086
|
+
if (element instanceof HTMLFormElement && !this.formActionIsVisitable(element, submitter)) {
|
|
3087
|
+
return false;
|
|
3088
|
+
}
|
|
2901
3089
|
if (!this.enabled || id == "_top") {
|
|
2902
3090
|
return false;
|
|
2903
3091
|
}
|
|
@@ -2954,6 +3142,28 @@ Copyright © 2021 Basecamp, LLC
|
|
|
2954
3142
|
get isActive() {
|
|
2955
3143
|
return this.element.isActive && this.connected;
|
|
2956
3144
|
}
|
|
3145
|
+
get rootLocation() {
|
|
3146
|
+
var _a;
|
|
3147
|
+
const meta = this.element.ownerDocument.querySelector(`meta[name="turbo-root"]`);
|
|
3148
|
+
const root = (_a = meta === null || meta === void 0 ? void 0 : meta.content) !== null && _a !== void 0 ? _a : "/";
|
|
3149
|
+
return expandURL(root);
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
class SnapshotSubstitution {
|
|
3153
|
+
constructor(element) {
|
|
3154
|
+
this.clone = element.cloneNode(true);
|
|
3155
|
+
this.id = element.id;
|
|
3156
|
+
}
|
|
3157
|
+
visitStarted(visit) {
|
|
3158
|
+
this.snapshot = visit.view.snapshot;
|
|
3159
|
+
}
|
|
3160
|
+
visitCachedSnapshot() {
|
|
3161
|
+
var _a;
|
|
3162
|
+
const { snapshot, id, clone } = this;
|
|
3163
|
+
if (snapshot) {
|
|
3164
|
+
(_a = snapshot.element.querySelector("#" + id)) === null || _a === void 0 ? void 0 : _a.replaceWith(clone);
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
2957
3167
|
}
|
|
2958
3168
|
function getFrameElementById(id) {
|
|
2959
3169
|
if (id != null) {
|
|
@@ -3149,10 +3359,11 @@ Copyright © 2021 Basecamp, LLC
|
|
|
3149
3359
|
exports.clearCache = clearCache;
|
|
3150
3360
|
exports.connectStreamSource = connectStreamSource;
|
|
3151
3361
|
exports.disconnectStreamSource = disconnectStreamSource;
|
|
3152
|
-
exports.navigator = navigator;
|
|
3362
|
+
exports.navigator = navigator$1;
|
|
3153
3363
|
exports.registerAdapter = registerAdapter;
|
|
3154
3364
|
exports.renderStreamMessage = renderStreamMessage;
|
|
3155
3365
|
exports.session = session;
|
|
3366
|
+
exports.setConfirmMethod = setConfirmMethod;
|
|
3156
3367
|
exports.setProgressBarDelay = setProgressBarDelay;
|
|
3157
3368
|
exports.start = start;
|
|
3158
3369
|
exports.visit = visit;
|