(function() {
if (window.Reflect === undefined || window.customElements === undefined || window.customElements.polyfillWrapFlushCallback) {
return;
}
const BuiltInHTMLElement = HTMLElement;
const wrapperForTheName = {
HTMLElement: function HTMLElement() {
return Reflect.construct(BuiltInHTMLElement, [], this.constructor);
}
};
window.HTMLElement = wrapperForTheName["HTMLElement"];
HTMLElement.prototype = BuiltInHTMLElement.prototype;
HTMLElement.prototype.constructor = HTMLElement;
Object.setPrototypeOf(HTMLElement, BuiltInHTMLElement);
})();
(function(prototype) {
if (typeof prototype.requestSubmit == "function") return;
prototype.requestSubmit = function(submitter) {
if (submitter) {
validateSubmitter(submitter, this);
submitter.click();
} else {
submitter = document.createElement("input");
submitter.type = "submit";
submitter.hidden = true;
this.appendChild(submitter);
submitter.click();
this.removeChild(submitter);
}
};
function validateSubmitter(submitter, form) {
submitter instanceof HTMLElement || raise(TypeError, "parameter 1 is not of type 'HTMLElement'");
submitter.type == "submit" || raise(TypeError, "The specified element is not a submit button");
submitter.form == form || raise(DOMException, "The specified element is not owned by this form element", "NotFoundError");
}
function raise(errorConstructor, message, name) {
throw new errorConstructor("Failed to execute 'requestSubmit' on 'HTMLFormElement': " + message + ".", name);
}
})(HTMLFormElement.prototype);
const submittersByForm = new WeakMap;
function findSubmitterFromClickTarget(target) {
const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
const candidate = element ? element.closest("input, button") : null;
return (candidate === null || candidate === void 0 ? void 0 : candidate.type) == "submit" ? candidate : null;
}
function clickCaptured(event) {
const submitter = findSubmitterFromClickTarget(event.target);
if (submitter && submitter.form) {
submittersByForm.set(submitter.form, submitter);
}
}
(function() {
if ("submitter" in Event.prototype) return;
let prototype = window.Event.prototype;
if ("SubmitEvent" in window && /Apple Computer/.test(navigator.vendor)) {
prototype = window.SubmitEvent.prototype;
} else if ("SubmitEvent" in window) {
return;
}
addEventListener("click", clickCaptured, true);
Object.defineProperty(prototype, "submitter", {
get() {
if (this.type == "submit" && this.target instanceof HTMLFormElement) {
return submittersByForm.get(this.target);
}
}
});
})();
var FrameLoadingStyle;
(function(FrameLoadingStyle) {
FrameLoadingStyle["eager"] = "eager";
FrameLoadingStyle["lazy"] = "lazy";
})(FrameLoadingStyle || (FrameLoadingStyle = {}));
class FrameElement extends HTMLElement {
static get observedAttributes() {
return [ "disabled", "complete", "loading", "src" ];
}
constructor() {
super();
this.loaded = Promise.resolve();
this.delegate = new FrameElement.delegateConstructor(this);
}
connectedCallback() {
this.delegate.connect();
}
disconnectedCallback() {
this.delegate.disconnect();
}
reload() {
return this.delegate.sourceURLReloaded();
}
attributeChangedCallback(name) {
if (name == "loading") {
this.delegate.loadingStyleChanged();
} else if (name == "complete") {
this.delegate.completeChanged();
} else if (name == "src") {
this.delegate.sourceURLChanged();
} else {
this.delegate.disabledChanged();
}
}
get src() {
return this.getAttribute("src");
}
set src(value) {
if (value) {
this.setAttribute("src", value);
} else {
this.removeAttribute("src");
}
}
get loading() {
return frameLoadingStyleFromString(this.getAttribute("loading") || "");
}
set loading(value) {
if (value) {
this.setAttribute("loading", value);
} else {
this.removeAttribute("loading");
}
}
get disabled() {
return this.hasAttribute("disabled");
}
set disabled(value) {
if (value) {
this.setAttribute("disabled", "");
} else {
this.removeAttribute("disabled");
}
}
get autoscroll() {
return this.hasAttribute("autoscroll");
}
set autoscroll(value) {
if (value) {
this.setAttribute("autoscroll", "");
} else {
this.removeAttribute("autoscroll");
}
}
get complete() {
return !this.delegate.isLoading;
}
get isActive() {
return this.ownerDocument === document && !this.isPreview;
}
get isPreview() {
var _a, _b;
return (_b = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.documentElement) === null || _b === void 0 ? void 0 : _b.hasAttribute("data-turbo-preview");
}
}
function frameLoadingStyleFromString(style) {
switch (style.toLowerCase()) {
case "lazy":
return FrameLoadingStyle.lazy;
default:
return FrameLoadingStyle.eager;
}
}
function expandURL(locatable) {
return new URL(locatable.toString(), document.baseURI);
}
function getAnchor(url) {
let anchorMatch;
if (url.hash) {
return url.hash.slice(1);
} else if (anchorMatch = url.href.match(/#(.*)$/)) {
return anchorMatch[1];
}
}
function getAction(form, submitter) {
const action = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formaction")) || form.getAttribute("action") || form.action;
return expandURL(action);
}
function getExtension(url) {
return (getLastPathComponent(url).match(/\.[^.]*$/) || [])[0] || "";
}
function isHTML(url) {
return !!getExtension(url).match(/^(?:|\.(?:htm|html|xhtml|php))$/);
}
function isPrefixedBy(baseURL, url) {
const prefix = getPrefix(url);
return baseURL.href === expandURL(prefix).href || baseURL.href.startsWith(prefix);
}
function locationIsVisitable(location, rootLocation) {
return isPrefixedBy(location, rootLocation) && isHTML(location);
}
function getRequestURL(url) {
const anchor = getAnchor(url);
return anchor != null ? url.href.slice(0, -(anchor.length + 1)) : url.href;
}
function toCacheKey(url) {
return getRequestURL(url);
}
function urlsAreEqual(left, right) {
return expandURL(left).href == expandURL(right).href;
}
function getPathComponents(url) {
return url.pathname.split("/").slice(1);
}
function getLastPathComponent(url) {
return getPathComponents(url).slice(-1)[0];
}
function getPrefix(url) {
return addTrailingSlash(url.origin + url.pathname);
}
function addTrailingSlash(value) {
return value.endsWith("/") ? value : value + "/";
}
class FetchResponse {
constructor(response) {
this.response = response;
}
get succeeded() {
return this.response.ok;
}
get failed() {
return !this.succeeded;
}
get clientError() {
return this.statusCode >= 400 && this.statusCode <= 499;
}
get serverError() {
return this.statusCode >= 500 && this.statusCode <= 599;
}
get redirected() {
return this.response.redirected;
}
get location() {
return expandURL(this.response.url);
}
get isHTML() {
return this.contentType && this.contentType.match(/^(?:text\/([^\s;,]+\b)?html|application\/xhtml\+xml)\b/);
}
get statusCode() {
return this.response.status;
}
get contentType() {
return this.header("Content-Type");
}
get responseText() {
return this.response.clone().text();
}
get responseHTML() {
if (this.isHTML) {
return this.response.clone().text();
} else {
return Promise.resolve(undefined);
}
}
header(name) {
return this.response.headers.get(name);
}
}
function activateScriptElement(element) {
if (element.getAttribute("data-turbo-eval") == "false") {
return element;
} else {
const createdScriptElement = document.createElement("script");
const cspNonce = getMetaContent("csp-nonce");
if (cspNonce) {
createdScriptElement.nonce = cspNonce;
}
createdScriptElement.textContent = element.textContent;
createdScriptElement.async = false;
copyElementAttributes(createdScriptElement, element);
return createdScriptElement;
}
}
function copyElementAttributes(destinationElement, sourceElement) {
for (const {name: name, value: value} of sourceElement.attributes) {
destinationElement.setAttribute(name, value);
}
}
function createDocumentFragment(html) {
const template = document.createElement("template");
template.innerHTML = html;
return template.content;
}
function dispatch(eventName, {target: target, cancelable: cancelable, detail: detail} = {}) {
const event = new CustomEvent(eventName, {
cancelable: cancelable,
bubbles: true,
composed: true,
detail: detail
});
if (target && target.isConnected) {
target.dispatchEvent(event);
} else {
document.documentElement.dispatchEvent(event);
}
return event;
}
function nextAnimationFrame() {
return new Promise((resolve => requestAnimationFrame((() => resolve()))));
}
function nextEventLoopTick() {
return new Promise((resolve => setTimeout((() => resolve()), 0)));
}
function nextMicrotask() {
return Promise.resolve();
}
function parseHTMLDocument(html = "") {
return (new DOMParser).parseFromString(html, "text/html");
}
function unindent(strings, ...values) {
const lines = interpolate(strings, values).replace(/^\n/, "").split("\n");
const match = lines[0].match(/^\s+/);
const indent = match ? match[0].length : 0;
return lines.map((line => line.slice(indent))).join("\n");
}
function interpolate(strings, values) {
return strings.reduce(((result, string, i) => {
const value = values[i] == undefined ? "" : values[i];
return result + string + value;
}), "");
}
function uuid() {
return Array.from({
length: 36
}).map(((_, i) => {
if (i == 8 || i == 13 || i == 18 || i == 23) {
return "-";
} else if (i == 14) {
return "4";
} else if (i == 19) {
return (Math.floor(Math.random() * 4) + 8).toString(16);
} else {
return Math.floor(Math.random() * 15).toString(16);
}
})).join("");
}
function getAttribute(attributeName, ...elements) {
for (const value of elements.map((element => element === null || element === void 0 ? void 0 : element.getAttribute(attributeName)))) {
if (typeof value == "string") return value;
}
return null;
}
function hasAttribute(attributeName, ...elements) {
return elements.some((element => element && element.hasAttribute(attributeName)));
}
function markAsBusy(...elements) {
for (const element of elements) {
if (element.localName == "turbo-frame") {
element.setAttribute("busy", "");
}
element.setAttribute("aria-busy", "true");
}
}
function clearBusyState(...elements) {
for (const element of elements) {
if (element.localName == "turbo-frame") {
element.removeAttribute("busy");
}
element.removeAttribute("aria-busy");
}
}
function waitForLoad(element, timeoutInMilliseconds = 2e3) {
return new Promise((resolve => {
const onComplete = () => {
element.removeEventListener("error", onComplete);
element.removeEventListener("load", onComplete);
resolve();
};
element.addEventListener("load", onComplete, {
once: true
});
element.addEventListener("error", onComplete, {
once: true
});
setTimeout(resolve, timeoutInMilliseconds);
}));
}
function getHistoryMethodForAction(action) {
switch (action) {
case "replace":
return history.replaceState;
case "advance":
case "restore":
return history.pushState;
}
}
function isAction(action) {
return action == "advance" || action == "replace" || action == "restore";
}
function getVisitAction(...elements) {
const action = getAttribute("data-turbo-action", ...elements);
return isAction(action) ? action : null;
}
function getMetaElement(name) {
return document.querySelector(`meta[name="${name}"]`);
}
function getMetaContent(name) {
const element = getMetaElement(name);
return element && element.content;
}
function setMetaContent(name, content) {
let element = getMetaElement(name);
if (!element) {
element = document.createElement("meta");
element.setAttribute("name", name);
document.head.appendChild(element);
}
element.setAttribute("content", content);
return element;
}
function findClosestRecursively(element, selector) {
var _a;
if (element instanceof Element) {
return element.closest(selector) || findClosestRecursively(element.assignedSlot || ((_a = element.getRootNode()) === null || _a === void 0 ? void 0 : _a.host), selector);
}
}
var FetchMethod;
(function(FetchMethod) {
FetchMethod[FetchMethod["get"] = 0] = "get";
FetchMethod[FetchMethod["post"] = 1] = "post";
FetchMethod[FetchMethod["put"] = 2] = "put";
FetchMethod[FetchMethod["patch"] = 3] = "patch";
FetchMethod[FetchMethod["delete"] = 4] = "delete";
})(FetchMethod || (FetchMethod = {}));
function fetchMethodFromString(method) {
switch (method.toLowerCase()) {
case "get":
return FetchMethod.get;
case "post":
return FetchMethod.post;
case "put":
return FetchMethod.put;
case "patch":
return FetchMethod.patch;
case "delete":
return FetchMethod.delete;
}
}
class FetchRequest {
constructor(delegate, method, location, body = new URLSearchParams, target = null) {
this.abortController = new AbortController;
this.resolveRequestPromise = _value => {};
this.delegate = delegate;
this.method = method;
this.headers = this.defaultHeaders;
this.body = body;
this.url = location;
this.target = target;
}
get location() {
return this.url;
}
get params() {
return this.url.searchParams;
}
get entries() {
return this.body ? Array.from(this.body.entries()) : [];
}
cancel() {
this.abortController.abort();
}
async perform() {
const {fetchOptions: fetchOptions} = this;
this.delegate.prepareRequest(this);
await this.allowRequestToBeIntercepted(fetchOptions);
try {
this.delegate.requestStarted(this);
const response = await fetch(this.url.href, fetchOptions);
return await this.receive(response);
} catch (error) {
if (error.name !== "AbortError") {
if (this.willDelegateErrorHandling(error)) {
this.delegate.requestErrored(this, error);
}
throw error;
}
} finally {
this.delegate.requestFinished(this);
}
}
async receive(response) {
const fetchResponse = new FetchResponse(response);
const event = dispatch("turbo:before-fetch-response", {
cancelable: true,
detail: {
fetchResponse: fetchResponse
},
target: this.target
});
if (event.defaultPrevented) {
this.delegate.requestPreventedHandlingResponse(this, fetchResponse);
} else if (fetchResponse.succeeded) {
this.delegate.requestSucceededWithResponse(this, fetchResponse);
} else {
this.delegate.requestFailedWithResponse(this, fetchResponse);
}
return fetchResponse;
}
get fetchOptions() {
var _a;
return {
method: FetchMethod[this.method].toUpperCase(),
credentials: "same-origin",
headers: this.headers,
redirect: "follow",
body: this.isSafe ? null : this.body,
signal: this.abortSignal,
referrer: (_a = this.delegate.referrer) === null || _a === void 0 ? void 0 : _a.href
};
}
get defaultHeaders() {
return {
Accept: "text/html, application/xhtml+xml"
};
}
get isSafe() {
return this.method === FetchMethod.get;
}
get abortSignal() {
return this.abortController.signal;
}
acceptResponseType(mimeType) {
this.headers["Accept"] = [ mimeType, this.headers["Accept"] ].join(", ");
}
async allowRequestToBeIntercepted(fetchOptions) {
const requestInterception = new Promise((resolve => this.resolveRequestPromise = resolve));
const event = dispatch("turbo:before-fetch-request", {
cancelable: true,
detail: {
fetchOptions: fetchOptions,
url: this.url,
resume: this.resolveRequestPromise
},
target: this.target
});
if (event.defaultPrevented) await requestInterception;
}
willDelegateErrorHandling(error) {
const event = dispatch("turbo:fetch-request-error", {
target: this.target,
cancelable: true,
detail: {
request: this,
error: error
}
});
return !event.defaultPrevented;
}
}
class AppearanceObserver {
constructor(delegate, element) {
this.started = false;
this.intersect = entries => {
const lastEntry = entries.slice(-1)[0];
if (lastEntry === null || lastEntry === void 0 ? void 0 : lastEntry.isIntersecting) {
this.delegate.elementAppearedInViewport(this.element);
}
};
this.delegate = delegate;
this.element = element;
this.intersectionObserver = new IntersectionObserver(this.intersect);
}
start() {
if (!this.started) {
this.started = true;
this.intersectionObserver.observe(this.element);
}
}
stop() {
if (this.started) {
this.started = false;
this.intersectionObserver.unobserve(this.element);
}
}
}
class StreamMessage {
static wrap(message) {
if (typeof message == "string") {
return new this(createDocumentFragment(message));
} else {
return message;
}
}
constructor(fragment) {
this.fragment = importStreamElements(fragment);
}
}
StreamMessage.contentType = "text/vnd.turbo-stream.html";
function importStreamElements(fragment) {
for (const element of fragment.querySelectorAll("turbo-stream")) {
const streamElement = document.importNode(element, true);
for (const inertScriptElement of streamElement.templateElement.content.querySelectorAll("script")) {
inertScriptElement.replaceWith(activateScriptElement(inertScriptElement));
}
element.replaceWith(streamElement);
}
return fragment;
}
var FormSubmissionState;
(function(FormSubmissionState) {
FormSubmissionState[FormSubmissionState["initialized"] = 0] = "initialized";
FormSubmissionState[FormSubmissionState["requesting"] = 1] = "requesting";
FormSubmissionState[FormSubmissionState["waiting"] = 2] = "waiting";
FormSubmissionState[FormSubmissionState["receiving"] = 3] = "receiving";
FormSubmissionState[FormSubmissionState["stopping"] = 4] = "stopping";
FormSubmissionState[FormSubmissionState["stopped"] = 5] = "stopped";
})(FormSubmissionState || (FormSubmissionState = {}));
var FormEnctype;
(function(FormEnctype) {
FormEnctype["urlEncoded"] = "application/x-www-form-urlencoded";
FormEnctype["multipart"] = "multipart/form-data";
FormEnctype["plain"] = "text/plain";
})(FormEnctype || (FormEnctype = {}));
function formEnctypeFromString(encoding) {
switch (encoding.toLowerCase()) {
case FormEnctype.multipart:
return FormEnctype.multipart;
case FormEnctype.plain:
return FormEnctype.plain;
default:
return FormEnctype.urlEncoded;
}
}
class FormSubmission {
static confirmMethod(message, _element, _submitter) {
return Promise.resolve(confirm(message));
}
constructor(delegate, formElement, submitter, mustRedirect = false) {
this.state = FormSubmissionState.initialized;
this.delegate = delegate;
this.formElement = formElement;
this.submitter = submitter;
this.formData = buildFormData(formElement, submitter);
this.location = expandURL(this.action);
if (this.method == FetchMethod.get) {
mergeFormDataEntries(this.location, [ ...this.body.entries() ]);
}
this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
this.mustRedirect = mustRedirect;
}
get method() {
var _a;
const method = ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formmethod")) || this.formElement.getAttribute("method") || "";
return fetchMethodFromString(method.toLowerCase()) || FetchMethod.get;
}
get action() {
var _a;
const formElementAction = typeof this.formElement.action === "string" ? this.formElement.action : null;
if ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.hasAttribute("formaction")) {
return this.submitter.getAttribute("formaction") || "";
} else {
return this.formElement.getAttribute("action") || formElementAction || "";
}
}
get body() {
if (this.enctype == FormEnctype.urlEncoded || this.method == FetchMethod.get) {
return new URLSearchParams(this.stringFormData);
} else {
return this.formData;
}
}
get enctype() {
var _a;
return formEnctypeFromString(((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formenctype")) || this.formElement.enctype);
}
get isSafe() {
return this.fetchRequest.isSafe;
}
get stringFormData() {
return [ ...this.formData ].reduce(((entries, [name, value]) => entries.concat(typeof value == "string" ? [ [ name, value ] ] : [])), []);
}
async start() {
const {initialized: initialized, requesting: requesting} = FormSubmissionState;
const confirmationMessage = getAttribute("data-turbo-confirm", this.submitter, this.formElement);
if (typeof confirmationMessage === "string") {
const answer = await FormSubmission.confirmMethod(confirmationMessage, this.formElement, this.submitter);
if (!answer) {
return;
}
}
if (this.state == initialized) {
this.state = requesting;
return this.fetchRequest.perform();
}
}
stop() {
const {stopping: stopping, stopped: stopped} = FormSubmissionState;
if (this.state != stopping && this.state != stopped) {
this.state = stopping;
this.fetchRequest.cancel();
return true;
}
}
prepareRequest(request) {
if (!request.isSafe) {
const token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token");
if (token) {
request.headers["X-CSRF-Token"] = token;
}
}
if (this.requestAcceptsTurboStreamResponse(request)) {
request.acceptResponseType(StreamMessage.contentType);
}
}
requestStarted(_request) {
var _a;
this.state = FormSubmissionState.waiting;
(_a = this.submitter) === null || _a === void 0 ? void 0 : _a.setAttribute("disabled", "");
this.setSubmitsWith();
dispatch("turbo:submit-start", {
target: this.formElement,
detail: {
formSubmission: this
}
});
this.delegate.formSubmissionStarted(this);
}
requestPreventedHandlingResponse(request, response) {
this.result = {
success: response.succeeded,
fetchResponse: response
};
}
requestSucceededWithResponse(request, response) {
if (response.clientError || response.serverError) {
this.delegate.formSubmissionFailedWithResponse(this, response);
} else if (this.requestMustRedirect(request) && responseSucceededWithoutRedirect(response)) {
const error = new Error("Form responses must redirect to another location");
this.delegate.formSubmissionErrored(this, error);
} else {
this.state = FormSubmissionState.receiving;
this.result = {
success: true,
fetchResponse: response
};
this.delegate.formSubmissionSucceededWithResponse(this, response);
}
}
requestFailedWithResponse(request, response) {
this.result = {
success: false,
fetchResponse: response
};
this.delegate.formSubmissionFailedWithResponse(this, response);
}
requestErrored(request, error) {
this.result = {
success: false,
error: error
};
this.delegate.formSubmissionErrored(this, error);
}
requestFinished(_request) {
var _a;
this.state = FormSubmissionState.stopped;
(_a = this.submitter) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled");
this.resetSubmitterText();
dispatch("turbo:submit-end", {
target: this.formElement,
detail: Object.assign({
formSubmission: this
}, this.result)
});
this.delegate.formSubmissionFinished(this);
}
setSubmitsWith() {
if (!this.submitter || !this.submitsWith) return;
if (this.submitter.matches("button")) {
this.originalSubmitText = this.submitter.innerHTML;
this.submitter.innerHTML = this.submitsWith;
} else if (this.submitter.matches("input")) {
const input = this.submitter;
this.originalSubmitText = input.value;
input.value = this.submitsWith;
}
}
resetSubmitterText() {
if (!this.submitter || !this.originalSubmitText) return;
if (this.submitter.matches("button")) {
this.submitter.innerHTML = this.originalSubmitText;
} else if (this.submitter.matches("input")) {
const input = this.submitter;
input.value = this.originalSubmitText;
}
}
requestMustRedirect(request) {
return !request.isSafe && this.mustRedirect;
}
requestAcceptsTurboStreamResponse(request) {
return !request.isSafe || hasAttribute("data-turbo-stream", this.submitter, this.formElement);
}
get submitsWith() {
var _a;
return (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("data-turbo-submits-with");
}
}
function buildFormData(formElement, submitter) {
const formData = new FormData(formElement);
const name = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("name");
const value = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("value");
if (name) {
formData.append(name, value || "");
}
return formData;
}
function getCookieValue(cookieName) {
if (cookieName != null) {
const cookies = document.cookie ? document.cookie.split("; ") : [];
const cookie = cookies.find((cookie => cookie.startsWith(cookieName)));
if (cookie) {
const value = cookie.split("=").slice(1).join("=");
return value ? decodeURIComponent(value) : undefined;
}
}
}
function responseSucceededWithoutRedirect(response) {
return response.statusCode == 200 && !response.redirected;
}
function mergeFormDataEntries(url, entries) {
const searchParams = new URLSearchParams;
for (const [name, value] of entries) {
if (value instanceof File) continue;
searchParams.append(name, value);
}
url.search = searchParams.toString();
return url;
}
class Snapshot {
constructor(element) {
this.element = element;
}
get activeElement() {
return this.element.ownerDocument.activeElement;
}
get children() {
return [ ...this.element.children ];
}
hasAnchor(anchor) {
return this.getElementForAnchor(anchor) != null;
}
getElementForAnchor(anchor) {
return anchor ? this.element.querySelector(`[id='${anchor}'], a[name='${anchor}']`) : null;
}
get isConnected() {
return this.element.isConnected;
}
get firstAutofocusableElement() {
const inertDisabledOrHidden = "[inert], :disabled, [hidden], details:not([open]), dialog:not([open])";
for (const element of this.element.querySelectorAll("[autofocus]")) {
if (element.closest(inertDisabledOrHidden) == null) return element; else continue;
}
return null;
}
get permanentElements() {
return queryPermanentElementsAll(this.element);
}
getPermanentElementById(id) {
return getPermanentElementById(this.element, id);
}
getPermanentElementMapForSnapshot(snapshot) {
const permanentElementMap = {};
for (const currentPermanentElement of this.permanentElements) {
const {id: id} = currentPermanentElement;
const newPermanentElement = snapshot.getPermanentElementById(id);
if (newPermanentElement) {
permanentElementMap[id] = [ currentPermanentElement, newPermanentElement ];
}
}
return permanentElementMap;
}
}
function getPermanentElementById(node, id) {
return node.querySelector(`#${id}[data-turbo-permanent]`);
}
function queryPermanentElementsAll(node) {
return node.querySelectorAll("[id][data-turbo-permanent]");
}
class FormSubmitObserver {
constructor(delegate, eventTarget) {
this.started = false;
this.submitCaptured = () => {
this.eventTarget.removeEventListener("submit", this.submitBubbled, false);
this.eventTarget.addEventListener("submit", this.submitBubbled, false);
};
this.submitBubbled = event => {
if (!event.defaultPrevented) {
const form = event.target instanceof HTMLFormElement ? event.target : undefined;
const submitter = event.submitter || undefined;
if (form && submissionDoesNotDismissDialog(form, submitter) && submissionDoesNotTargetIFrame(form, submitter) && this.delegate.willSubmitForm(form, submitter)) {
event.preventDefault();
event.stopImmediatePropagation();
this.delegate.formSubmitted(form, submitter);
}
}
};
this.delegate = delegate;
this.eventTarget = eventTarget;
}
start() {
if (!this.started) {
this.eventTarget.addEventListener("submit", this.submitCaptured, true);
this.started = true;
}
}
stop() {
if (this.started) {
this.eventTarget.removeEventListener("submit", this.submitCaptured, true);
this.started = false;
}
}
}
function submissionDoesNotDismissDialog(form, submitter) {
const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.getAttribute("method");
return method != "dialog";
}
function submissionDoesNotTargetIFrame(form, submitter) {
if ((submitter === null || submitter === void 0 ? void 0 : submitter.hasAttribute("formtarget")) || form.hasAttribute("target")) {
const target = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formtarget")) || form.target;
for (const element of document.getElementsByName(target)) {
if (element instanceof HTMLIFrameElement) return false;
}
return true;
} else {
return true;
}
}
class View {
constructor(delegate, element) {
this.resolveRenderPromise = _value => {};
this.resolveInterceptionPromise = _value => {};
this.delegate = delegate;
this.element = element;
}
scrollToAnchor(anchor) {
const element = this.snapshot.getElementForAnchor(anchor);
if (element) {
this.scrollToElement(element);
this.focusElement(element);
} else {
this.scrollToPosition({
x: 0,
y: 0
});
}
}
scrollToAnchorFromLocation(location) {
this.scrollToAnchor(getAnchor(location));
}
scrollToElement(element) {
element.scrollIntoView();
}
focusElement(element) {
if (element instanceof HTMLElement) {
if (element.hasAttribute("tabindex")) {
element.focus();
} else {
element.setAttribute("tabindex", "-1");
element.focus();
element.removeAttribute("tabindex");
}
}
}
scrollToPosition({x: x, y: y}) {
this.scrollRoot.scrollTo(x, y);
}
scrollToTop() {
this.scrollToPosition({
x: 0,
y: 0
});
}
get scrollRoot() {
return window;
}
async render(renderer) {
const {isPreview: isPreview, shouldRender: shouldRender, newSnapshot: snapshot} = renderer;
if (shouldRender) {
try {
this.renderPromise = new Promise((resolve => this.resolveRenderPromise = resolve));
this.renderer = renderer;
await this.prepareToRenderSnapshot(renderer);
const renderInterception = new Promise((resolve => this.resolveInterceptionPromise = resolve));
const options = {
resume: this.resolveInterceptionPromise,
render: this.renderer.renderElement
};
const immediateRender = this.delegate.allowsImmediateRender(snapshot, options);
if (!immediateRender) await renderInterception;
await this.renderSnapshot(renderer);
this.delegate.viewRenderedSnapshot(snapshot, isPreview);
this.delegate.preloadOnLoadLinksForView(this.element);
this.finishRenderingSnapshot(renderer);
} finally {
delete this.renderer;
this.resolveRenderPromise(undefined);
delete this.renderPromise;
}
} else {
this.invalidate(renderer.reloadReason);
}
}
invalidate(reason) {
this.delegate.viewInvalidated(reason);
}
async prepareToRenderSnapshot(renderer) {
this.markAsPreview(renderer.isPreview);
await renderer.prepareToRender();
}
markAsPreview(isPreview) {
if (isPreview) {
this.element.setAttribute("data-turbo-preview", "");
} else {
this.element.removeAttribute("data-turbo-preview");
}
}
async renderSnapshot(renderer) {
await renderer.render();
}
finishRenderingSnapshot(renderer) {
renderer.finishRendering();
}
}
class FrameView extends View {
missing() {
this.element.innerHTML = `Content missing`;
}
get snapshot() {
return new Snapshot(this.element);
}
}
class LinkInterceptor {
constructor(delegate, element) {
this.clickBubbled = event => {
if (this.respondsToEventTarget(event.target)) {
this.clickEvent = event;
} else {
delete this.clickEvent;
}
};
this.linkClicked = event => {
if (this.clickEvent && this.respondsToEventTarget(event.target) && event.target instanceof Element) {
if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url, event.detail.originalEvent)) {
this.clickEvent.preventDefault();
event.preventDefault();
this.delegate.linkClickIntercepted(event.target, event.detail.url, event.detail.originalEvent);
}
}
delete this.clickEvent;
};
this.willVisit = _event => {
delete this.clickEvent;
};
this.delegate = delegate;
this.element = element;
}
start() {
this.element.addEventListener("click", this.clickBubbled);
document.addEventListener("turbo:click", this.linkClicked);
document.addEventListener("turbo:before-visit", this.willVisit);
}
stop() {
this.element.removeEventListener("click", this.clickBubbled);
document.removeEventListener("turbo:click", this.linkClicked);
document.removeEventListener("turbo:before-visit", this.willVisit);
}
respondsToEventTarget(target) {
const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
return element && element.closest("turbo-frame, html") == this.element;
}
}
class LinkClickObserver {
constructor(delegate, eventTarget) {
this.started = false;
this.clickCaptured = () => {
this.eventTarget.removeEventListener("click", this.clickBubbled, false);
this.eventTarget.addEventListener("click", this.clickBubbled, false);
};
this.clickBubbled = event => {
if (event instanceof MouseEvent && this.clickEventIsSignificant(event)) {
const target = event.composedPath && event.composedPath()[0] || event.target;
const link = this.findLinkFromClickTarget(target);
if (link && doesNotTargetIFrame(link)) {
const location = this.getLocationForLink(link);
if (this.delegate.willFollowLinkToLocation(link, location, event)) {
event.preventDefault();
this.delegate.followedLinkToLocation(link, location);
}
}
}
};
this.delegate = delegate;
this.eventTarget = eventTarget;
}
start() {
if (!this.started) {
this.eventTarget.addEventListener("click", this.clickCaptured, true);
this.started = true;
}
}
stop() {
if (this.started) {
this.eventTarget.removeEventListener("click", this.clickCaptured, true);
this.started = false;
}
}
clickEventIsSignificant(event) {
return !(event.target && event.target.isContentEditable || event.defaultPrevented || event.which > 1 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey);
}
findLinkFromClickTarget(target) {
return findClosestRecursively(target, "a[href]:not([target^=_]):not([download])");
}
getLocationForLink(link) {
return expandURL(link.getAttribute("href") || "");
}
}
function doesNotTargetIFrame(anchor) {
if (anchor.hasAttribute("target")) {
for (const element of document.getElementsByName(anchor.target)) {
if (element instanceof HTMLIFrameElement) return false;
}
return true;
} else {
return true;
}
}
class FormLinkClickObserver {
constructor(delegate, element) {
this.delegate = delegate;
this.linkInterceptor = new LinkClickObserver(this, element);
}
start() {
this.linkInterceptor.start();
}
stop() {
this.linkInterceptor.stop();
}
willFollowLinkToLocation(link, location, originalEvent) {
return this.delegate.willSubmitFormLinkToLocation(link, location, originalEvent) && link.hasAttribute("data-turbo-method");
}
followedLinkToLocation(link, location) {
const form = document.createElement("form");
const type = "hidden";
for (const [name, value] of location.searchParams) {
form.append(Object.assign(document.createElement("input"), {
type: type,
name: name,
value: value
}));
}
const action = Object.assign(location, {
search: ""
});
form.setAttribute("data-turbo", "true");
form.setAttribute("action", action.href);
form.setAttribute("hidden", "");
const method = link.getAttribute("data-turbo-method");
if (method) form.setAttribute("method", method);
const turboFrame = link.getAttribute("data-turbo-frame");
if (turboFrame) form.setAttribute("data-turbo-frame", turboFrame);
const turboAction = getVisitAction(link);
if (turboAction) form.setAttribute("data-turbo-action", turboAction);
const turboConfirm = link.getAttribute("data-turbo-confirm");
if (turboConfirm) form.setAttribute("data-turbo-confirm", turboConfirm);
const turboStream = link.hasAttribute("data-turbo-stream");
if (turboStream) form.setAttribute("data-turbo-stream", "");
this.delegate.submittedFormLinkToLocation(link, location, form);
document.body.appendChild(form);
form.addEventListener("turbo:submit-end", (() => form.remove()), {
once: true
});
requestAnimationFrame((() => form.requestSubmit()));
}
}
class Bardo {
static async preservingPermanentElements(delegate, permanentElementMap, callback) {
const bardo = new this(delegate, permanentElementMap);
bardo.enter();
await callback();
bardo.leave();
}
constructor(delegate, permanentElementMap) {
this.delegate = delegate;
this.permanentElementMap = permanentElementMap;
}
enter() {
for (const id in this.permanentElementMap) {
const [currentPermanentElement, newPermanentElement] = this.permanentElementMap[id];
this.delegate.enteringBardo(currentPermanentElement, newPermanentElement);
this.replaceNewPermanentElementWithPlaceholder(newPermanentElement);
}
}
leave() {
for (const id in this.permanentElementMap) {
const [currentPermanentElement] = this.permanentElementMap[id];
this.replaceCurrentPermanentElementWithClone(currentPermanentElement);
this.replacePlaceholderWithPermanentElement(currentPermanentElement);
this.delegate.leavingBardo(currentPermanentElement);
}
}
replaceNewPermanentElementWithPlaceholder(permanentElement) {
const placeholder = createPlaceholderForPermanentElement(permanentElement);
permanentElement.replaceWith(placeholder);
}
replaceCurrentPermanentElementWithClone(permanentElement) {
const clone = permanentElement.cloneNode(true);
permanentElement.replaceWith(clone);
}
replacePlaceholderWithPermanentElement(permanentElement) {
const placeholder = this.getPlaceholderById(permanentElement.id);
placeholder === null || placeholder === void 0 ? void 0 : placeholder.replaceWith(permanentElement);
}
getPlaceholderById(id) {
return this.placeholders.find((element => element.content == id));
}
get placeholders() {
return [ ...document.querySelectorAll("meta[name=turbo-permanent-placeholder][content]") ];
}
}
function createPlaceholderForPermanentElement(permanentElement) {
const element = document.createElement("meta");
element.setAttribute("name", "turbo-permanent-placeholder");
element.setAttribute("content", permanentElement.id);
return element;
}
class Renderer {
constructor(currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
this.activeElement = null;
this.currentSnapshot = currentSnapshot;
this.newSnapshot = newSnapshot;
this.isPreview = isPreview;
this.willRender = willRender;
this.renderElement = renderElement;
this.promise = new Promise(((resolve, reject) => this.resolvingFunctions = {
resolve: resolve,
reject: reject
}));
}
get shouldRender() {
return true;
}
get reloadReason() {
return;
}
prepareToRender() {
return;
}
finishRendering() {
if (this.resolvingFunctions) {
this.resolvingFunctions.resolve();
delete this.resolvingFunctions;
}
}
async preservingPermanentElements(callback) {
await Bardo.preservingPermanentElements(this, this.permanentElementMap, callback);
}
focusFirstAutofocusableElement() {
const element = this.connectedSnapshot.firstAutofocusableElement;
if (elementIsFocusable(element)) {
element.focus();
}
}
enteringBardo(currentPermanentElement) {
if (this.activeElement) return;
if (currentPermanentElement.contains(this.currentSnapshot.activeElement)) {
this.activeElement = this.currentSnapshot.activeElement;
}
}
leavingBardo(currentPermanentElement) {
if (currentPermanentElement.contains(this.activeElement) && this.activeElement instanceof HTMLElement) {
this.activeElement.focus();
this.activeElement = null;
}
}
get connectedSnapshot() {
return this.newSnapshot.isConnected ? this.newSnapshot : this.currentSnapshot;
}
get currentElement() {
return this.currentSnapshot.element;
}
get newElement() {
return this.newSnapshot.element;
}
get permanentElementMap() {
return this.currentSnapshot.getPermanentElementMapForSnapshot(this.newSnapshot);
}
}
function elementIsFocusable(element) {
return element && typeof element.focus == "function";
}
class FrameRenderer extends Renderer {
static renderElement(currentElement, newElement) {
var _a;
const destinationRange = document.createRange();
destinationRange.selectNodeContents(currentElement);
destinationRange.deleteContents();
const frameElement = newElement;
const sourceRange = (_a = frameElement.ownerDocument) === null || _a === void 0 ? void 0 : _a.createRange();
if (sourceRange) {
sourceRange.selectNodeContents(frameElement);
currentElement.appendChild(sourceRange.extractContents());
}
}
constructor(delegate, currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
super(currentSnapshot, newSnapshot, renderElement, isPreview, willRender);
this.delegate = delegate;
}
get shouldRender() {
return true;
}
async render() {
await nextAnimationFrame();
this.preservingPermanentElements((() => {
this.loadFrameElement();
}));
this.scrollFrameIntoView();
await nextAnimationFrame();
this.focusFirstAutofocusableElement();
await nextAnimationFrame();
this.activateScriptElements();
}
loadFrameElement() {
this.delegate.willRenderFrame(this.currentElement, this.newElement);
this.renderElement(this.currentElement, this.newElement);
}
scrollFrameIntoView() {
if (this.currentElement.autoscroll || this.newElement.autoscroll) {
const element = this.currentElement.firstElementChild;
const block = readScrollLogicalPosition(this.currentElement.getAttribute("data-autoscroll-block"), "end");
const behavior = readScrollBehavior(this.currentElement.getAttribute("data-autoscroll-behavior"), "auto");
if (element) {
element.scrollIntoView({
block: block,
behavior: behavior
});
return true;
}
}
return false;
}
activateScriptElements() {
for (const inertScriptElement of this.newScriptElements) {
const activatedScriptElement = activateScriptElement(inertScriptElement);
inertScriptElement.replaceWith(activatedScriptElement);
}
}
get newScriptElements() {
return this.currentElement.querySelectorAll("script");
}
}
function readScrollLogicalPosition(value, defaultValue) {
if (value == "end" || value == "start" || value == "center" || value == "nearest") {
return value;
} else {
return defaultValue;
}
}
function readScrollBehavior(value, defaultValue) {
if (value == "auto" || value == "smooth") {
return value;
} else {
return defaultValue;
}
}
class ProgressBar {
static get defaultCSS() {
return unindent`
.turbo-progress-bar {
position: fixed;
display: block;
top: 0;
left: 0;
height: 3px;
background: #0076ff;
z-index: 2147483647;
transition:
width ${ProgressBar.animationDuration}ms ease-out,
opacity ${ProgressBar.animationDuration / 2}ms ${ProgressBar.animationDuration / 2}ms ease-in;
transform: translate3d(0, 0, 0);
}
`;
}
constructor() {
this.hiding = false;
this.value = 0;
this.visible = false;
this.trickle = () => {
this.setValue(this.value + Math.random() / 100);
};
this.stylesheetElement = this.createStylesheetElement();
this.progressElement = this.createProgressElement();
this.installStylesheetElement();
this.setValue(0);
}
show() {
if (!this.visible) {
this.visible = true;
this.installProgressElement();
this.startTrickling();
}
}
hide() {
if (this.visible && !this.hiding) {
this.hiding = true;
this.fadeProgressElement((() => {
this.uninstallProgressElement();
this.stopTrickling();
this.visible = false;
this.hiding = false;
}));
}
}
setValue(value) {
this.value = value;
this.refresh();
}
installStylesheetElement() {
document.head.insertBefore(this.stylesheetElement, document.head.firstChild);
}
installProgressElement() {
this.progressElement.style.width = "0";
this.progressElement.style.opacity = "1";
document.documentElement.insertBefore(this.progressElement, document.body);
this.refresh();
}
fadeProgressElement(callback) {
this.progressElement.style.opacity = "0";
setTimeout(callback, ProgressBar.animationDuration * 1.5);
}
uninstallProgressElement() {
if (this.progressElement.parentNode) {
document.documentElement.removeChild(this.progressElement);
}
}
startTrickling() {
if (!this.trickleInterval) {
this.trickleInterval = window.setInterval(this.trickle, ProgressBar.animationDuration);
}
}
stopTrickling() {
window.clearInterval(this.trickleInterval);
delete this.trickleInterval;
}
refresh() {
requestAnimationFrame((() => {
this.progressElement.style.width = `${10 + this.value * 90}%`;
}));
}
createStylesheetElement() {
const element = document.createElement("style");
element.type = "text/css";
element.textContent = ProgressBar.defaultCSS;
if (this.cspNonce) {
element.nonce = this.cspNonce;
}
return element;
}
createProgressElement() {
const element = document.createElement("div");
element.className = "turbo-progress-bar";
return element;
}
get cspNonce() {
return getMetaContent("csp-nonce");
}
}
ProgressBar.animationDuration = 300;
class HeadSnapshot extends Snapshot {
constructor() {
super(...arguments);
this.detailsByOuterHTML = this.children.filter((element => !elementIsNoscript(element))).map((element => elementWithoutNonce(element))).reduce(((result, element) => {
const {outerHTML: outerHTML} = element;
const details = outerHTML in result ? result[outerHTML] : {
type: elementType(element),
tracked: elementIsTracked(element),
elements: []
};
return Object.assign(Object.assign({}, result), {
[outerHTML]: Object.assign(Object.assign({}, details), {
elements: [ ...details.elements, element ]
})
});
}), {});
}
get trackedElementSignature() {
return Object.keys(this.detailsByOuterHTML).filter((outerHTML => this.detailsByOuterHTML[outerHTML].tracked)).join("");
}
getScriptElementsNotInSnapshot(snapshot) {
return this.getElementsMatchingTypeNotInSnapshot("script", snapshot);
}
getStylesheetElementsNotInSnapshot(snapshot) {
return this.getElementsMatchingTypeNotInSnapshot("stylesheet", snapshot);
}
getElementsMatchingTypeNotInSnapshot(matchedType, snapshot) {
return Object.keys(this.detailsByOuterHTML).filter((outerHTML => !(outerHTML in snapshot.detailsByOuterHTML))).map((outerHTML => this.detailsByOuterHTML[outerHTML])).filter((({type: type}) => type == matchedType)).map((({elements: [element]}) => element));
}
get provisionalElements() {
return Object.keys(this.detailsByOuterHTML).reduce(((result, outerHTML) => {
const {type: type, tracked: tracked, elements: elements} = this.detailsByOuterHTML[outerHTML];
if (type == null && !tracked) {
return [ ...result, ...elements ];
} else if (elements.length > 1) {
return [ ...result, ...elements.slice(1) ];
} else {
return result;
}
}), []);
}
getMetaValue(name) {
const element = this.findMetaElementByName(name);
return element ? element.getAttribute("content") : null;
}
findMetaElementByName(name) {
return Object.keys(this.detailsByOuterHTML).reduce(((result, outerHTML) => {
const {elements: [element]} = this.detailsByOuterHTML[outerHTML];
return elementIsMetaElementWithName(element, name) ? element : result;
}), undefined);
}
}
function elementType(element) {
if (elementIsScript(element)) {
return "script";
} else if (elementIsStylesheet(element)) {
return "stylesheet";
}
}
function elementIsTracked(element) {
return element.getAttribute("data-turbo-track") == "reload";
}
function elementIsScript(element) {
const tagName = element.localName;
return tagName == "script";
}
function elementIsNoscript(element) {
const tagName = element.localName;
return tagName == "noscript";
}
function elementIsStylesheet(element) {
const tagName = element.localName;
return tagName == "style" || tagName == "link" && element.getAttribute("rel") == "stylesheet";
}
function elementIsMetaElementWithName(element, name) {
const tagName = element.localName;
return tagName == "meta" && element.getAttribute("name") == name;
}
function elementWithoutNonce(element) {
if (element.hasAttribute("nonce")) {
element.setAttribute("nonce", "");
}
return element;
}
class PageSnapshot extends Snapshot {
static fromHTMLString(html = "") {
return this.fromDocument(parseHTMLDocument(html));
}
static fromElement(element) {
return this.fromDocument(element.ownerDocument);
}
static fromDocument({head: head, body: body}) {
return new this(body, new HeadSnapshot(head));
}
constructor(element, headSnapshot) {
super(element);
this.headSnapshot = headSnapshot;
}
clone() {
const clonedElement = this.element.cloneNode(true);
const selectElements = this.element.querySelectorAll("select");
const clonedSelectElements = clonedElement.querySelectorAll("select");
for (const [index, source] of selectElements.entries()) {
const clone = clonedSelectElements[index];
for (const option of clone.selectedOptions) option.selected = false;
for (const option of source.selectedOptions) clone.options[option.index].selected = true;
}
for (const clonedPasswordInput of clonedElement.querySelectorAll('input[type="password"]')) {
clonedPasswordInput.value = "";
}
return new PageSnapshot(clonedElement, this.headSnapshot);
}
get headElement() {
return this.headSnapshot.element;
}
get rootLocation() {
var _a;
const root = (_a = this.getSetting("root")) !== null && _a !== void 0 ? _a : "/";
return expandURL(root);
}
get cacheControlValue() {
return this.getSetting("cache-control");
}
get isPreviewable() {
return this.cacheControlValue != "no-preview";
}
get isCacheable() {
return this.cacheControlValue != "no-cache";
}
get isVisitable() {
return this.getSetting("visit-control") != "reload";
}
getSetting(name) {
return this.headSnapshot.getMetaValue(`turbo-${name}`);
}
}
var TimingMetric;
(function(TimingMetric) {
TimingMetric["visitStart"] = "visitStart";
TimingMetric["requestStart"] = "requestStart";
TimingMetric["requestEnd"] = "requestEnd";
TimingMetric["visitEnd"] = "visitEnd";
})(TimingMetric || (TimingMetric = {}));
var VisitState;
(function(VisitState) {
VisitState["initialized"] = "initialized";
VisitState["started"] = "started";
VisitState["canceled"] = "canceled";
VisitState["failed"] = "failed";
VisitState["completed"] = "completed";
})(VisitState || (VisitState = {}));
const defaultOptions = {
action: "advance",
historyChanged: false,
visitCachedSnapshot: () => {},
willRender: true,
updateHistory: true,
shouldCacheSnapshot: true,
acceptsStreamResponse: false
};
var SystemStatusCode;
(function(SystemStatusCode) {
SystemStatusCode[SystemStatusCode["networkFailure"] = 0] = "networkFailure";
SystemStatusCode[SystemStatusCode["timeoutFailure"] = -1] = "timeoutFailure";
SystemStatusCode[SystemStatusCode["contentTypeMismatch"] = -2] = "contentTypeMismatch";
})(SystemStatusCode || (SystemStatusCode = {}));
class Visit {
constructor(delegate, location, restorationIdentifier, options = {}) {
this.identifier = uuid();
this.timingMetrics = {};
this.followedRedirect = false;
this.historyChanged = false;
this.scrolled = false;
this.shouldCacheSnapshot = true;
this.acceptsStreamResponse = false;
this.snapshotCached = false;
this.state = VisitState.initialized;
this.delegate = delegate;
this.location = location;
this.restorationIdentifier = restorationIdentifier || uuid();
const {action: action, historyChanged: historyChanged, referrer: referrer, snapshot: snapshot, snapshotHTML: snapshotHTML, response: response, visitCachedSnapshot: visitCachedSnapshot, willRender: willRender, updateHistory: updateHistory, shouldCacheSnapshot: shouldCacheSnapshot, acceptsStreamResponse: acceptsStreamResponse} = Object.assign(Object.assign({}, defaultOptions), options);
this.action = action;
this.historyChanged = historyChanged;
this.referrer = referrer;
this.snapshot = snapshot;
this.snapshotHTML = snapshotHTML;
this.response = response;
this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action);
this.visitCachedSnapshot = visitCachedSnapshot;
this.willRender = willRender;
this.updateHistory = updateHistory;
this.scrolled = !willRender;
this.shouldCacheSnapshot = shouldCacheSnapshot;
this.acceptsStreamResponse = acceptsStreamResponse;
}
get adapter() {
return this.delegate.adapter;
}
get view() {
return this.delegate.view;
}
get history() {
return this.delegate.history;
}
get restorationData() {
return this.history.getRestorationDataForIdentifier(this.restorationIdentifier);
}
get silent() {
return this.isSamePage;
}
start() {
if (this.state == VisitState.initialized) {
this.recordTimingMetric(TimingMetric.visitStart);
this.state = VisitState.started;
this.adapter.visitStarted(this);
this.delegate.visitStarted(this);
}
}
cancel() {
if (this.state == VisitState.started) {
if (this.request) {
this.request.cancel();
}
this.cancelRender();
this.state = VisitState.canceled;
}
}
complete() {
if (this.state == VisitState.started) {
this.recordTimingMetric(TimingMetric.visitEnd);
this.state = VisitState.completed;
this.followRedirect();
if (!this.followedRedirect) {
this.adapter.visitCompleted(this);
this.delegate.visitCompleted(this);
}
}
}
fail() {
if (this.state == VisitState.started) {
this.state = VisitState.failed;
this.adapter.visitFailed(this);
}
}
changeHistory() {
var _a;
if (!this.historyChanged && this.updateHistory) {
const actionForHistory = this.location.href === ((_a = this.referrer) === null || _a === void 0 ? void 0 : _a.href) ? "replace" : this.action;
const method = getHistoryMethodForAction(actionForHistory);
this.history.update(method, this.location, this.restorationIdentifier);
this.historyChanged = true;
}
}
issueRequest() {
if (this.hasPreloadedResponse()) {
this.simulateRequest();
} else if (this.shouldIssueRequest() && !this.request) {
this.request = new FetchRequest(this, FetchMethod.get, this.location);
this.request.perform();
}
}
simulateRequest() {
if (this.response) {
this.startRequest();
this.recordResponse();
this.finishRequest();
}
}
startRequest() {
this.recordTimingMetric(TimingMetric.requestStart);
this.adapter.visitRequestStarted(this);
}
recordResponse(response = this.response) {
this.response = response;
if (response) {
const {statusCode: statusCode} = response;
if (isSuccessful(statusCode)) {
this.adapter.visitRequestCompleted(this);
} else {
this.adapter.visitRequestFailedWithStatusCode(this, statusCode);
}
}
}
finishRequest() {
this.recordTimingMetric(TimingMetric.requestEnd);
this.adapter.visitRequestFinished(this);
}
loadResponse() {
if (this.response) {
const {statusCode: statusCode, responseHTML: responseHTML} = this.response;
this.render((async () => {
if (this.shouldCacheSnapshot) this.cacheSnapshot();
if (this.view.renderPromise) await this.view.renderPromise;
if (isSuccessful(statusCode) && responseHTML != null) {
await this.view.renderPage(PageSnapshot.fromHTMLString(responseHTML), false, this.willRender, this);
this.performScroll();
this.adapter.visitRendered(this);
this.complete();
} else {
await this.view.renderError(PageSnapshot.fromHTMLString(responseHTML), this);
this.adapter.visitRendered(this);
this.fail();
}
}));
}
}
getCachedSnapshot() {
const snapshot = this.view.getCachedSnapshotForLocation(this.location) || this.getPreloadedSnapshot();
if (snapshot && (!getAnchor(this.location) || snapshot.hasAnchor(getAnchor(this.location)))) {
if (this.action == "restore" || snapshot.isPreviewable) {
return snapshot;
}
}
}
getPreloadedSnapshot() {
if (this.snapshotHTML) {
return PageSnapshot.fromHTMLString(this.snapshotHTML);
}
}
hasCachedSnapshot() {
return this.getCachedSnapshot() != null;
}
loadCachedSnapshot() {
const snapshot = this.getCachedSnapshot();
if (snapshot) {
const isPreview = this.shouldIssueRequest();
this.render((async () => {
this.cacheSnapshot();
if (this.isSamePage) {
this.adapter.visitRendered(this);
} else {
if (this.view.renderPromise) await this.view.renderPromise;
await this.view.renderPage(snapshot, isPreview, this.willRender, this);
this.performScroll();
this.adapter.visitRendered(this);
if (!isPreview) {
this.complete();
}
}
}));
}
}
followRedirect() {
var _a;
if (this.redirectedToLocation && !this.followedRedirect && ((_a = this.response) === null || _a === void 0 ? void 0 : _a.redirected)) {
this.adapter.visitProposedToLocation(this.redirectedToLocation, {
action: "replace",
response: this.response,
shouldCacheSnapshot: false,
willRender: false
});
this.followedRedirect = true;
}
}
goToSamePageAnchor() {
if (this.isSamePage) {
this.render((async () => {
this.cacheSnapshot();
this.performScroll();
this.changeHistory();
this.adapter.visitRendered(this);
}));
}
}
prepareRequest(request) {
if (this.acceptsStreamResponse) {
request.acceptResponseType(StreamMessage.contentType);
}
}
requestStarted() {
this.startRequest();
}
requestPreventedHandlingResponse(_request, _response) {}
async requestSucceededWithResponse(request, response) {
const responseHTML = await response.responseHTML;
const {redirected: redirected, statusCode: statusCode} = response;
if (responseHTML == undefined) {
this.recordResponse({
statusCode: SystemStatusCode.contentTypeMismatch,
redirected: redirected
});
} else {
this.redirectedToLocation = response.redirected ? response.location : undefined;
this.recordResponse({
statusCode: statusCode,
responseHTML: responseHTML,
redirected: redirected
});
}
}
async requestFailedWithResponse(request, response) {
const responseHTML = await response.responseHTML;
const {redirected: redirected, statusCode: statusCode} = response;
if (responseHTML == undefined) {
this.recordResponse({
statusCode: SystemStatusCode.contentTypeMismatch,
redirected: redirected
});
} else {
this.recordResponse({
statusCode: statusCode,
responseHTML: responseHTML,
redirected: redirected
});
}
}
requestErrored(_request, _error) {
this.recordResponse({
statusCode: SystemStatusCode.networkFailure,
redirected: false
});
}
requestFinished() {
this.finishRequest();
}
performScroll() {
if (!this.scrolled && !this.view.forceReloaded) {
if (this.action == "restore") {
this.scrollToRestoredPosition() || this.scrollToAnchor() || this.view.scrollToTop();
} else {
this.scrollToAnchor() || this.view.scrollToTop();
}
if (this.isSamePage) {
this.delegate.visitScrolledToSamePageLocation(this.view.lastRenderedLocation, this.location);
}
this.scrolled = true;
}
}
scrollToRestoredPosition() {
const {scrollPosition: scrollPosition} = this.restorationData;
if (scrollPosition) {
this.view.scrollToPosition(scrollPosition);
return true;
}
}
scrollToAnchor() {
const anchor = getAnchor(this.location);
if (anchor != null) {
this.view.scrollToAnchor(anchor);
return true;
}
}
recordTimingMetric(metric) {
this.timingMetrics[metric] = (new Date).getTime();
}
getTimingMetrics() {
return Object.assign({}, this.timingMetrics);
}
getHistoryMethodForAction(action) {
switch (action) {
case "replace":
return history.replaceState;
case "advance":
case "restore":
return history.pushState;
}
}
hasPreloadedResponse() {
return typeof this.response == "object";
}
shouldIssueRequest() {
if (this.isSamePage) {
return false;
} else if (this.action == "restore") {
return !this.hasCachedSnapshot();
} else {
return this.willRender;
}
}
cacheSnapshot() {
if (!this.snapshotCached) {
this.view.cacheSnapshot(this.snapshot).then((snapshot => snapshot && this.visitCachedSnapshot(snapshot)));
this.snapshotCached = true;
}
}
async render(callback) {
this.cancelRender();
await new Promise((resolve => {
this.frame = requestAnimationFrame((() => resolve()));
}));
await callback();
delete this.frame;
}
cancelRender() {
if (this.frame) {
cancelAnimationFrame(this.frame);
delete this.frame;
}
}
}
function isSuccessful(statusCode) {
return statusCode >= 200 && statusCode < 300;
}
class BrowserAdapter {
constructor(session) {
this.progressBar = new ProgressBar;
this.showProgressBar = () => {
this.progressBar.show();
};
this.session = session;
}
visitProposedToLocation(location, options) {
this.navigator.startVisit(location, (options === null || options === void 0 ? void 0 : options.restorationIdentifier) || uuid(), options);
}
visitStarted(visit) {
this.location = visit.location;
visit.loadCachedSnapshot();
visit.issueRequest();
visit.goToSamePageAnchor();
}
visitRequestStarted(visit) {
this.progressBar.setValue(0);
if (visit.hasCachedSnapshot() || visit.action != "restore") {
this.showVisitProgressBarAfterDelay();
} else {
this.showProgressBar();
}
}
visitRequestCompleted(visit) {
visit.loadResponse();
}
visitRequestFailedWithStatusCode(visit, statusCode) {
switch (statusCode) {
case SystemStatusCode.networkFailure:
case SystemStatusCode.timeoutFailure:
case SystemStatusCode.contentTypeMismatch:
return this.reload({
reason: "request_failed",
context: {
statusCode: statusCode
}
});
default:
return visit.loadResponse();
}
}
visitRequestFinished(_visit) {
this.progressBar.setValue(1);
this.hideVisitProgressBar();
}
visitCompleted(_visit) {}
pageInvalidated(reason) {
this.reload(reason);
}
visitFailed(_visit) {}
visitRendered(_visit) {}
formSubmissionStarted(_formSubmission) {
this.progressBar.setValue(0);
this.showFormProgressBarAfterDelay();
}
formSubmissionFinished(_formSubmission) {
this.progressBar.setValue(1);
this.hideFormProgressBar();
}
showVisitProgressBarAfterDelay() {
this.visitProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay);
}
hideVisitProgressBar() {
this.progressBar.hide();
if (this.visitProgressBarTimeout != null) {
window.clearTimeout(this.visitProgressBarTimeout);
delete this.visitProgressBarTimeout;
}
}
showFormProgressBarAfterDelay() {
if (this.formProgressBarTimeout == null) {
this.formProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay);
}
}
hideFormProgressBar() {
this.progressBar.hide();
if (this.formProgressBarTimeout != null) {
window.clearTimeout(this.formProgressBarTimeout);
delete this.formProgressBarTimeout;
}
}
reload(reason) {
var _a;
dispatch("turbo:reload", {
detail: reason
});
window.location.href = ((_a = this.location) === null || _a === void 0 ? void 0 : _a.toString()) || window.location.href;
}
get navigator() {
return this.session.navigator;
}
}
class CacheObserver {
constructor() {
this.selector = "[data-turbo-temporary]";
this.deprecatedSelector = "[data-turbo-cache=false]";
this.started = false;
this.removeTemporaryElements = _event => {
for (const element of this.temporaryElements) {
element.remove();
}
};
}
start() {
if (!this.started) {
this.started = true;
addEventListener("turbo:before-cache", this.removeTemporaryElements, false);
}
}
stop() {
if (this.started) {
this.started = false;
removeEventListener("turbo:before-cache", this.removeTemporaryElements, false);
}
}
get temporaryElements() {
return [ ...document.querySelectorAll(this.selector), ...this.temporaryElementsWithDeprecation ];
}
get temporaryElementsWithDeprecation() {
const elements = document.querySelectorAll(this.deprecatedSelector);
if (elements.length) {
console.warn(`The ${this.deprecatedSelector} selector is deprecated and will be removed in a future version. Use ${this.selector} instead.`);
}
return [ ...elements ];
}
}
class FrameRedirector {
constructor(session, element) {
this.session = session;
this.element = element;
this.linkInterceptor = new LinkInterceptor(this, element);
this.formSubmitObserver = new FormSubmitObserver(this, element);
}
start() {
this.linkInterceptor.start();
this.formSubmitObserver.start();
}
stop() {
this.linkInterceptor.stop();
this.formSubmitObserver.stop();
}
shouldInterceptLinkClick(element, _location, _event) {
return this.shouldRedirect(element);
}
linkClickIntercepted(element, url, event) {
const frame = this.findFrameElement(element);
if (frame) {
frame.delegate.linkClickIntercepted(element, url, event);
}
}
willSubmitForm(element, submitter) {
return element.closest("turbo-frame") == null && this.shouldSubmit(element, submitter) && this.shouldRedirect(element, submitter);
}
formSubmitted(element, submitter) {
const frame = this.findFrameElement(element, submitter);
if (frame) {
frame.delegate.formSubmitted(element, submitter);
}
}
shouldSubmit(form, submitter) {
var _a;
const action = getAction(form, submitter);
const meta = this.element.ownerDocument.querySelector(`meta[name="turbo-root"]`);
const rootLocation = expandURL((_a = meta === null || meta === void 0 ? void 0 : meta.content) !== null && _a !== void 0 ? _a : "/");
return this.shouldRedirect(form, submitter) && locationIsVisitable(action, rootLocation);
}
shouldRedirect(element, submitter) {
const isNavigatable = element instanceof HTMLFormElement ? this.session.submissionIsNavigatable(element, submitter) : this.session.elementIsNavigatable(element);
if (isNavigatable) {
const frame = this.findFrameElement(element, submitter);
return frame ? frame != element.closest("turbo-frame") : false;
} else {
return false;
}
}
findFrameElement(element, submitter) {
const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame");
if (id && id != "_top") {
const frame = this.element.querySelector(`#${id}:not([disabled])`);
if (frame instanceof FrameElement) {
return frame;
}
}
}
}
class History {
constructor(delegate) {
this.restorationIdentifier = uuid();
this.restorationData = {};
this.started = false;
this.pageLoaded = false;
this.onPopState = event => {
if (this.shouldHandlePopState()) {
const {turbo: turbo} = event.state || {};
if (turbo) {
this.location = new URL(window.location.href);
const {restorationIdentifier: restorationIdentifier} = turbo;
this.restorationIdentifier = restorationIdentifier;
this.delegate.historyPoppedToLocationWithRestorationIdentifier(this.location, restorationIdentifier);
}
}
};
this.onPageLoad = async _event => {
await nextMicrotask();
this.pageLoaded = true;
};
this.delegate = delegate;
}
start() {
if (!this.started) {
addEventListener("popstate", this.onPopState, false);
addEventListener("load", this.onPageLoad, false);
this.started = true;
this.replace(new URL(window.location.href));
}
}
stop() {
if (this.started) {
removeEventListener("popstate", this.onPopState, false);
removeEventListener("load", this.onPageLoad, false);
this.started = false;
}
}
push(location, restorationIdentifier) {
this.update(history.pushState, location, restorationIdentifier);
}
replace(location, restorationIdentifier) {
this.update(history.replaceState, location, restorationIdentifier);
}
update(method, location, restorationIdentifier = uuid()) {
const state = {
turbo: {
restorationIdentifier: restorationIdentifier
}
};
method.call(history, state, "", location.href);
this.location = location;
this.restorationIdentifier = restorationIdentifier;
}
getRestorationDataForIdentifier(restorationIdentifier) {
return this.restorationData[restorationIdentifier] || {};
}
updateRestorationData(additionalData) {
const {restorationIdentifier: restorationIdentifier} = this;
const restorationData = this.restorationData[restorationIdentifier];
this.restorationData[restorationIdentifier] = Object.assign(Object.assign({}, restorationData), additionalData);
}
assumeControlOfScrollRestoration() {
var _a;
if (!this.previousScrollRestoration) {
this.previousScrollRestoration = (_a = history.scrollRestoration) !== null && _a !== void 0 ? _a : "auto";
history.scrollRestoration = "manual";
}
}
relinquishControlOfScrollRestoration() {
if (this.previousScrollRestoration) {
history.scrollRestoration = this.previousScrollRestoration;
delete this.previousScrollRestoration;
}
}
shouldHandlePopState() {
return this.pageIsLoaded();
}
pageIsLoaded() {
return this.pageLoaded || document.readyState == "complete";
}
}
class Navigator {
constructor(delegate) {
this.delegate = delegate;
}
proposeVisit(location, options = {}) {
if (this.delegate.allowsVisitingLocationWithAction(location, options.action)) {
if (locationIsVisitable(location, this.view.snapshot.rootLocation)) {
this.delegate.visitProposedToLocation(location, options);
} else {
window.location.href = location.toString();
}
}
}
startVisit(locatable, restorationIdentifier, options = {}) {
this.stop();
this.currentVisit = new Visit(this, expandURL(locatable), restorationIdentifier, Object.assign({
referrer: this.location
}, options));
this.currentVisit.start();
}
submitForm(form, submitter) {
this.stop();
this.formSubmission = new FormSubmission(this, form, submitter, true);
this.formSubmission.start();
}
stop() {
if (this.formSubmission) {
this.formSubmission.stop();
delete this.formSubmission;
}
if (this.currentVisit) {
this.currentVisit.cancel();
delete this.currentVisit;
}
}
get adapter() {
return this.delegate.adapter;
}
get view() {
return this.delegate.view;
}
get history() {
return this.delegate.history;
}
formSubmissionStarted(formSubmission) {
if (typeof this.adapter.formSubmissionStarted === "function") {
this.adapter.formSubmissionStarted(formSubmission);
}
}
async formSubmissionSucceededWithResponse(formSubmission, fetchResponse) {
if (formSubmission == this.formSubmission) {
const responseHTML = await fetchResponse.responseHTML;
if (responseHTML) {
const shouldCacheSnapshot = formSubmission.isSafe;
if (!shouldCacheSnapshot) {
this.view.clearSnapshotCache();
}
const {statusCode: statusCode, redirected: redirected} = fetchResponse;
const action = this.getActionForFormSubmission(formSubmission);
const visitOptions = {
action: action,
shouldCacheSnapshot: shouldCacheSnapshot,
response: {
statusCode: statusCode,
responseHTML: responseHTML,
redirected: redirected
}
};
this.proposeVisit(fetchResponse.location, visitOptions);
}
}
}
async formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
const responseHTML = await fetchResponse.responseHTML;
if (responseHTML) {
const snapshot = PageSnapshot.fromHTMLString(responseHTML);
if (fetchResponse.serverError) {
await this.view.renderError(snapshot, this.currentVisit);
} else {
await this.view.renderPage(snapshot, false, true, this.currentVisit);
}
this.view.scrollToTop();
this.view.clearSnapshotCache();
}
}
formSubmissionErrored(formSubmission, error) {
console.error(error);
}
formSubmissionFinished(formSubmission) {
if (typeof this.adapter.formSubmissionFinished === "function") {
this.adapter.formSubmissionFinished(formSubmission);
}
}
visitStarted(visit) {
this.delegate.visitStarted(visit);
}
visitCompleted(visit) {
this.delegate.visitCompleted(visit);
}
locationWithActionIsSamePage(location, action) {
const anchor = getAnchor(location);
const currentAnchor = getAnchor(this.view.lastRenderedLocation);
const isRestorationToTop = action === "restore" && typeof anchor === "undefined";
return action !== "replace" && getRequestURL(location) === getRequestURL(this.view.lastRenderedLocation) && (isRestorationToTop || anchor != null && anchor !== currentAnchor);
}
visitScrolledToSamePageLocation(oldURL, newURL) {
this.delegate.visitScrolledToSamePageLocation(oldURL, newURL);
}
get location() {
return this.history.location;
}
get restorationIdentifier() {
return this.history.restorationIdentifier;
}
getActionForFormSubmission({submitter: submitter, formElement: formElement}) {
return getVisitAction(submitter, formElement) || "advance";
}
}
var PageStage;
(function(PageStage) {
PageStage[PageStage["initial"] = 0] = "initial";
PageStage[PageStage["loading"] = 1] = "loading";
PageStage[PageStage["interactive"] = 2] = "interactive";
PageStage[PageStage["complete"] = 3] = "complete";
})(PageStage || (PageStage = {}));
class PageObserver {
constructor(delegate) {
this.stage = PageStage.initial;
this.started = false;
this.interpretReadyState = () => {
const {readyState: readyState} = this;
if (readyState == "interactive") {
this.pageIsInteractive();
} else if (readyState == "complete") {
this.pageIsComplete();
}
};
this.pageWillUnload = () => {
this.delegate.pageWillUnload();
};
this.delegate = delegate;
}
start() {
if (!this.started) {
if (this.stage == PageStage.initial) {
this.stage = PageStage.loading;
}
document.addEventListener("readystatechange", this.interpretReadyState, false);
addEventListener("pagehide", this.pageWillUnload, false);
this.started = true;
}
}
stop() {
if (this.started) {
document.removeEventListener("readystatechange", this.interpretReadyState, false);
removeEventListener("pagehide", this.pageWillUnload, false);
this.started = false;
}
}
pageIsInteractive() {
if (this.stage == PageStage.loading) {
this.stage = PageStage.interactive;
this.delegate.pageBecameInteractive();
}
}
pageIsComplete() {
this.pageIsInteractive();
if (this.stage == PageStage.interactive) {
this.stage = PageStage.complete;
this.delegate.pageLoaded();
}
}
get readyState() {
return document.readyState;
}
}
class ScrollObserver {
constructor(delegate) {
this.started = false;
this.onScroll = () => {
this.updatePosition({
x: window.pageXOffset,
y: window.pageYOffset
});
};
this.delegate = delegate;
}
start() {
if (!this.started) {
addEventListener("scroll", this.onScroll, false);
this.onScroll();
this.started = true;
}
}
stop() {
if (this.started) {
removeEventListener("scroll", this.onScroll, false);
this.started = false;
}
}
updatePosition(position) {
this.delegate.scrollPositionChanged(position);
}
}
class StreamMessageRenderer {
render({fragment: fragment}) {
Bardo.preservingPermanentElements(this, getPermanentElementMapForFragment(fragment), (() => document.documentElement.appendChild(fragment)));
}
enteringBardo(currentPermanentElement, newPermanentElement) {
newPermanentElement.replaceWith(currentPermanentElement.cloneNode(true));
}
leavingBardo() {}
}
function getPermanentElementMapForFragment(fragment) {
const permanentElementsInDocument = queryPermanentElementsAll(document.documentElement);
const permanentElementMap = {};
for (const permanentElementInDocument of permanentElementsInDocument) {
const {id: id} = permanentElementInDocument;
for (const streamElement of fragment.querySelectorAll("turbo-stream")) {
const elementInStream = getPermanentElementById(streamElement.templateElement.content, id);
if (elementInStream) {
permanentElementMap[id] = [ permanentElementInDocument, elementInStream ];
}
}
}
return permanentElementMap;
}
class StreamObserver {
constructor(delegate) {
this.sources = new Set;
this.started = false;
this.inspectFetchResponse = event => {
const response = fetchResponseFromEvent(event);
if (response && fetchResponseIsStream(response)) {
event.preventDefault();
this.receiveMessageResponse(response);
}
};
this.receiveMessageEvent = event => {
if (this.started && typeof event.data == "string") {
this.receiveMessageHTML(event.data);
}
};
this.delegate = delegate;
}
start() {
if (!this.started) {
this.started = true;
addEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false);
}
}
stop() {
if (this.started) {
this.started = false;
removeEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false);
}
}
connectStreamSource(source) {
if (!this.streamSourceIsConnected(source)) {
this.sources.add(source);
source.addEventListener("message", this.receiveMessageEvent, false);
}
}
disconnectStreamSource(source) {
if (this.streamSourceIsConnected(source)) {
this.sources.delete(source);
source.removeEventListener("message", this.receiveMessageEvent, false);
}
}
streamSourceIsConnected(source) {
return this.sources.has(source);
}
async receiveMessageResponse(response) {
const html = await response.responseHTML;
if (html) {
this.receiveMessageHTML(html);
}
}
receiveMessageHTML(html) {
this.delegate.receivedMessageFromStream(StreamMessage.wrap(html));
}
}
function fetchResponseFromEvent(event) {
var _a;
const fetchResponse = (_a = event.detail) === null || _a === void 0 ? void 0 : _a.fetchResponse;
if (fetchResponse instanceof FetchResponse) {
return fetchResponse;
}
}
function fetchResponseIsStream(response) {
var _a;
const contentType = (_a = response.contentType) !== null && _a !== void 0 ? _a : "";
return contentType.startsWith(StreamMessage.contentType);
}
class ErrorRenderer extends Renderer {
static renderElement(currentElement, newElement) {
const {documentElement: documentElement, body: body} = document;
documentElement.replaceChild(newElement, body);
}
async render() {
this.replaceHeadAndBody();
this.activateScriptElements();
}
replaceHeadAndBody() {
const {documentElement: documentElement, head: head} = document;
documentElement.replaceChild(this.newHead, head);
this.renderElement(this.currentElement, this.newElement);
}
activateScriptElements() {
for (const replaceableElement of this.scriptElements) {
const parentNode = replaceableElement.parentNode;
if (parentNode) {
const element = activateScriptElement(replaceableElement);
parentNode.replaceChild(element, replaceableElement);
}
}
}
get newHead() {
return this.newSnapshot.headSnapshot.element;
}
get scriptElements() {
return document.documentElement.querySelectorAll("script");
}
}
class PageRenderer extends Renderer {
static renderElement(currentElement, newElement) {
if (document.body && newElement instanceof HTMLBodyElement) {
document.body.replaceWith(newElement);
} else {
document.documentElement.appendChild(newElement);
}
}
get shouldRender() {
return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical;
}
get reloadReason() {
if (!this.newSnapshot.isVisitable) {
return {
reason: "turbo_visit_control_is_reload"
};
}
if (!this.trackedElementsAreIdentical) {
return {
reason: "tracked_element_mismatch"
};
}
}
async prepareToRender() {
await this.mergeHead();
}
async render() {
if (this.willRender) {
await this.replaceBody();
}
}
finishRendering() {
super.finishRendering();
if (!this.isPreview) {
this.focusFirstAutofocusableElement();
}
}
get currentHeadSnapshot() {
return this.currentSnapshot.headSnapshot;
}
get newHeadSnapshot() {
return this.newSnapshot.headSnapshot;
}
get newElement() {
return this.newSnapshot.element;
}
async mergeHead() {
const mergedHeadElements = this.mergeProvisionalElements();
const newStylesheetElements = this.copyNewHeadStylesheetElements();
this.copyNewHeadScriptElements();
await mergedHeadElements;
await newStylesheetElements;
}
async replaceBody() {
await this.preservingPermanentElements((async () => {
this.activateNewBody();
await this.assignNewBody();
}));
}
get trackedElementsAreIdentical() {
return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature;
}
async copyNewHeadStylesheetElements() {
const loadingElements = [];
for (const element of this.newHeadStylesheetElements) {
loadingElements.push(waitForLoad(element));
document.head.appendChild(element);
}
await Promise.all(loadingElements);
}
copyNewHeadScriptElements() {
for (const element of this.newHeadScriptElements) {
document.head.appendChild(activateScriptElement(element));
}
}
async mergeProvisionalElements() {
const newHeadElements = [ ...this.newHeadProvisionalElements ];
for (const element of this.currentHeadProvisionalElements) {
if (!this.isCurrentElementInElementList(element, newHeadElements)) {
document.head.removeChild(element);
}
}
for (const element of newHeadElements) {
document.head.appendChild(element);
}
}
isCurrentElementInElementList(element, elementList) {
for (const [index, newElement] of elementList.entries()) {
if (element.tagName == "TITLE") {
if (newElement.tagName != "TITLE") {
continue;
}
if (element.innerHTML == newElement.innerHTML) {
elementList.splice(index, 1);
return true;
}
}
if (newElement.isEqualNode(element)) {
elementList.splice(index, 1);
return true;
}
}
return false;
}
removeCurrentHeadProvisionalElements() {
for (const element of this.currentHeadProvisionalElements) {
document.head.removeChild(element);
}
}
copyNewHeadProvisionalElements() {
for (const element of this.newHeadProvisionalElements) {
document.head.appendChild(element);
}
}
activateNewBody() {
document.adoptNode(this.newElement);
this.activateNewBodyScriptElements();
}
activateNewBodyScriptElements() {
for (const inertScriptElement of this.newBodyScriptElements) {
const activatedScriptElement = activateScriptElement(inertScriptElement);
inertScriptElement.replaceWith(activatedScriptElement);
}
}
async assignNewBody() {
await this.renderElement(this.currentElement, this.newElement);
}
get newHeadStylesheetElements() {
return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot);
}
get newHeadScriptElements() {
return this.newHeadSnapshot.getScriptElementsNotInSnapshot(this.currentHeadSnapshot);
}
get currentHeadProvisionalElements() {
return this.currentHeadSnapshot.provisionalElements;
}
get newHeadProvisionalElements() {
return this.newHeadSnapshot.provisionalElements;
}
get newBodyScriptElements() {
return this.newElement.querySelectorAll("script");
}
}
class SnapshotCache {
constructor(size) {
this.keys = [];
this.snapshots = {};
this.size = size;
}
has(location) {
return toCacheKey(location) in this.snapshots;
}
get(location) {
if (this.has(location)) {
const snapshot = this.read(location);
this.touch(location);
return snapshot;
}
}
put(location, snapshot) {
this.write(location, snapshot);
this.touch(location);
return snapshot;
}
clear() {
this.snapshots = {};
}
read(location) {
return this.snapshots[toCacheKey(location)];
}
write(location, snapshot) {
this.snapshots[toCacheKey(location)] = snapshot;
}
touch(location) {
const key = toCacheKey(location);
const index = this.keys.indexOf(key);
if (index > -1) this.keys.splice(index, 1);
this.keys.unshift(key);
this.trim();
}
trim() {
for (const key of this.keys.splice(this.size)) {
delete this.snapshots[key];
}
}
}
class PageView extends View {
constructor() {
super(...arguments);
this.snapshotCache = new SnapshotCache(10);
this.lastRenderedLocation = new URL(location.href);
this.forceReloaded = false;
}
renderPage(snapshot, isPreview = false, willRender = true, visit) {
const renderer = new PageRenderer(this.snapshot, snapshot, PageRenderer.renderElement, isPreview, willRender);
if (!renderer.shouldRender) {
this.forceReloaded = true;
} else {
visit === null || visit === void 0 ? void 0 : visit.changeHistory();
}
return this.render(renderer);
}
renderError(snapshot, visit) {
visit === null || visit === void 0 ? void 0 : visit.changeHistory();
const renderer = new ErrorRenderer(this.snapshot, snapshot, ErrorRenderer.renderElement, false);
return this.render(renderer);
}
clearSnapshotCache() {
this.snapshotCache.clear();
}
async cacheSnapshot(snapshot = this.snapshot) {
if (snapshot.isCacheable) {
this.delegate.viewWillCacheSnapshot();
const {lastRenderedLocation: location} = this;
await nextEventLoopTick();
const cachedSnapshot = snapshot.clone();
this.snapshotCache.put(location, cachedSnapshot);
return cachedSnapshot;
}
}
getCachedSnapshotForLocation(location) {
return this.snapshotCache.get(location);
}
get snapshot() {
return PageSnapshot.fromElement(this.element);
}
}
class Preloader {
constructor(delegate) {
this.selector = "a[data-turbo-preload]";
this.delegate = delegate;
}
get snapshotCache() {
return this.delegate.navigator.view.snapshotCache;
}
start() {
if (document.readyState === "loading") {
return document.addEventListener("DOMContentLoaded", (() => {
this.preloadOnLoadLinksForView(document.body);
}));
} else {
this.preloadOnLoadLinksForView(document.body);
}
}
preloadOnLoadLinksForView(element) {
for (const link of element.querySelectorAll(this.selector)) {
this.preloadURL(link);
}
}
async preloadURL(link) {
const location = new URL(link.href);
if (this.snapshotCache.has(location)) {
return;
}
try {
const response = await fetch(location.toString(), {
headers: {
"VND.PREFETCH": "true",
Accept: "text/html"
}
});
const responseText = await response.text();
const snapshot = PageSnapshot.fromHTMLString(responseText);
this.snapshotCache.put(location, snapshot);
} catch (_) {}
}
}
class Session {
constructor() {
this.navigator = new Navigator(this);
this.history = new History(this);
this.preloader = new Preloader(this);
this.view = new PageView(this, document.documentElement);
this.adapter = new BrowserAdapter(this);
this.pageObserver = new PageObserver(this);
this.cacheObserver = new CacheObserver;
this.linkClickObserver = new LinkClickObserver(this, window);
this.formSubmitObserver = new FormSubmitObserver(this, document);
this.scrollObserver = new ScrollObserver(this);
this.streamObserver = new StreamObserver(this);
this.formLinkClickObserver = new FormLinkClickObserver(this, document.documentElement);
this.frameRedirector = new FrameRedirector(this, document.documentElement);
this.streamMessageRenderer = new StreamMessageRenderer;
this.drive = true;
this.enabled = true;
this.progressBarDelay = 500;
this.started = false;
this.formMode = "on";
}
start() {
if (!this.started) {
this.pageObserver.start();
this.cacheObserver.start();
this.formLinkClickObserver.start();
this.linkClickObserver.start();
this.formSubmitObserver.start();
this.scrollObserver.start();
this.streamObserver.start();
this.frameRedirector.start();
this.history.start();
this.preloader.start();
this.started = true;
this.enabled = true;
}
}
disable() {
this.enabled = false;
}
stop() {
if (this.started) {
this.pageObserver.stop();
this.cacheObserver.stop();
this.formLinkClickObserver.stop();
this.linkClickObserver.stop();
this.formSubmitObserver.stop();
this.scrollObserver.stop();
this.streamObserver.stop();
this.frameRedirector.stop();
this.history.stop();
this.started = false;
}
}
registerAdapter(adapter) {
this.adapter = adapter;
}
visit(location, options = {}) {
const frameElement = options.frame ? document.getElementById(options.frame) : null;
if (frameElement instanceof FrameElement) {
frameElement.src = location.toString();
frameElement.loaded;
} else {
this.navigator.proposeVisit(expandURL(location), options);
}
}
connectStreamSource(source) {
this.streamObserver.connectStreamSource(source);
}
disconnectStreamSource(source) {
this.streamObserver.disconnectStreamSource(source);
}
renderStreamMessage(message) {
this.streamMessageRenderer.render(StreamMessage.wrap(message));
}
clearCache() {
this.view.clearSnapshotCache();
}
setProgressBarDelay(delay) {
this.progressBarDelay = delay;
}
setFormMode(mode) {
this.formMode = mode;
}
get location() {
return this.history.location;
}
get restorationIdentifier() {
return this.history.restorationIdentifier;
}
historyPoppedToLocationWithRestorationIdentifier(location, restorationIdentifier) {
if (this.enabled) {
this.navigator.startVisit(location, restorationIdentifier, {
action: "restore",
historyChanged: true
});
} else {
this.adapter.pageInvalidated({
reason: "turbo_disabled"
});
}
}
scrollPositionChanged(position) {
this.history.updateRestorationData({
scrollPosition: position
});
}
willSubmitFormLinkToLocation(link, location) {
return this.elementIsNavigatable(link) && locationIsVisitable(location, this.snapshot.rootLocation);
}
submittedFormLinkToLocation() {}
willFollowLinkToLocation(link, location, event) {
return this.elementIsNavigatable(link) && locationIsVisitable(location, this.snapshot.rootLocation) && this.applicationAllowsFollowingLinkToLocation(link, location, event);
}
followedLinkToLocation(link, location) {
const action = this.getActionForLink(link);
const acceptsStreamResponse = link.hasAttribute("data-turbo-stream");
this.visit(location.href, {
action: action,
acceptsStreamResponse: acceptsStreamResponse
});
}
allowsVisitingLocationWithAction(location, action) {
return this.locationWithActionIsSamePage(location, action) || this.applicationAllowsVisitingLocation(location);
}
visitProposedToLocation(location, options) {
extendURLWithDeprecatedProperties(location);
this.adapter.visitProposedToLocation(location, options);
}
visitStarted(visit) {
if (!visit.acceptsStreamResponse) {
markAsBusy(document.documentElement);
}
extendURLWithDeprecatedProperties(visit.location);
if (!visit.silent) {
this.notifyApplicationAfterVisitingLocation(visit.location, visit.action);
}
}
visitCompleted(visit) {
clearBusyState(document.documentElement);
this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());
}
locationWithActionIsSamePage(location, action) {
return this.navigator.locationWithActionIsSamePage(location, action);
}
visitScrolledToSamePageLocation(oldURL, newURL) {
this.notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL);
}
willSubmitForm(form, submitter) {
const action = getAction(form, submitter);
return this.submissionIsNavigatable(form, submitter) && locationIsVisitable(expandURL(action), this.snapshot.rootLocation);
}
formSubmitted(form, submitter) {
this.navigator.submitForm(form, submitter);
}
pageBecameInteractive() {
this.view.lastRenderedLocation = this.location;
this.notifyApplicationAfterPageLoad();
}
pageLoaded() {
this.history.assumeControlOfScrollRestoration();
}
pageWillUnload() {
this.history.relinquishControlOfScrollRestoration();
}
receivedMessageFromStream(message) {
this.renderStreamMessage(message);
}
viewWillCacheSnapshot() {
var _a;
if (!((_a = this.navigator.currentVisit) === null || _a === void 0 ? void 0 : _a.silent)) {
this.notifyApplicationBeforeCachingSnapshot();
}
}
allowsImmediateRender({element: element}, options) {
const event = this.notifyApplicationBeforeRender(element, options);
const {defaultPrevented: defaultPrevented, detail: {render: render}} = event;
if (this.view.renderer && render) {
this.view.renderer.renderElement = render;
}
return !defaultPrevented;
}
viewRenderedSnapshot(_snapshot, _isPreview) {
this.view.lastRenderedLocation = this.history.location;
this.notifyApplicationAfterRender();
}
preloadOnLoadLinksForView(element) {
this.preloader.preloadOnLoadLinksForView(element);
}
viewInvalidated(reason) {
this.adapter.pageInvalidated(reason);
}
frameLoaded(frame) {
this.notifyApplicationAfterFrameLoad(frame);
}
frameRendered(fetchResponse, frame) {
this.notifyApplicationAfterFrameRender(fetchResponse, frame);
}
applicationAllowsFollowingLinkToLocation(link, location, ev) {
const event = this.notifyApplicationAfterClickingLinkToLocation(link, location, ev);
return !event.defaultPrevented;
}
applicationAllowsVisitingLocation(location) {
const event = this.notifyApplicationBeforeVisitingLocation(location);
return !event.defaultPrevented;
}
notifyApplicationAfterClickingLinkToLocation(link, location, event) {
return dispatch("turbo:click", {
target: link,
detail: {
url: location.href,
originalEvent: event
},
cancelable: true
});
}
notifyApplicationBeforeVisitingLocation(location) {
return dispatch("turbo:before-visit", {
detail: {
url: location.href
},
cancelable: true
});
}
notifyApplicationAfterVisitingLocation(location, action) {
return dispatch("turbo:visit", {
detail: {
url: location.href,
action: action
}
});
}
notifyApplicationBeforeCachingSnapshot() {
return dispatch("turbo:before-cache");
}
notifyApplicationBeforeRender(newBody, options) {
return dispatch("turbo:before-render", {
detail: Object.assign({
newBody: newBody
}, options),
cancelable: true
});
}
notifyApplicationAfterRender() {
return dispatch("turbo:render");
}
notifyApplicationAfterPageLoad(timing = {}) {
return dispatch("turbo:load", {
detail: {
url: this.location.href,
timing: timing
}
});
}
notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL) {
dispatchEvent(new HashChangeEvent("hashchange", {
oldURL: oldURL.toString(),
newURL: newURL.toString()
}));
}
notifyApplicationAfterFrameLoad(frame) {
return dispatch("turbo:frame-load", {
target: frame
});
}
notifyApplicationAfterFrameRender(fetchResponse, frame) {
return dispatch("turbo:frame-render", {
detail: {
fetchResponse: fetchResponse
},
target: frame,
cancelable: true
});
}
submissionIsNavigatable(form, submitter) {
if (this.formMode == "off") {
return false;
} else {
const submitterIsNavigatable = submitter ? this.elementIsNavigatable(submitter) : true;
if (this.formMode == "optin") {
return submitterIsNavigatable && form.closest('[data-turbo="true"]') != null;
} else {
return submitterIsNavigatable && this.elementIsNavigatable(form);
}
}
}
elementIsNavigatable(element) {
const container = findClosestRecursively(element, "[data-turbo]");
const withinFrame = findClosestRecursively(element, "turbo-frame");
if (this.drive || withinFrame) {
if (container) {
return container.getAttribute("data-turbo") != "false";
} else {
return true;
}
} else {
if (container) {
return container.getAttribute("data-turbo") == "true";
} else {
return false;
}
}
}
getActionForLink(link) {
return getVisitAction(link) || "advance";
}
get snapshot() {
return this.view.snapshot;
}
}
function extendURLWithDeprecatedProperties(url) {
Object.defineProperties(url, deprecatedLocationPropertyDescriptors);
}
const deprecatedLocationPropertyDescriptors = {
absoluteURL: {
get() {
return this.toString();
}
}
};
class Cache {
constructor(session) {
this.session = session;
}
clear() {
this.session.clearCache();
}
resetCacheControl() {
this.setCacheControl("");
}
exemptPageFromCache() {
this.setCacheControl("no-cache");
}
exemptPageFromPreview() {
this.setCacheControl("no-preview");
}
setCacheControl(value) {
setMetaContent("turbo-cache-control", value);
}
}
const StreamActions = {
after() {
this.targetElements.forEach((e => {
var _a;
return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e.nextSibling);
}));
},
append() {
this.removeDuplicateTargetChildren();
this.targetElements.forEach((e => e.append(this.templateContent)));
},
before() {
this.targetElements.forEach((e => {
var _a;
return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e);
}));
},
prepend() {
this.removeDuplicateTargetChildren();
this.targetElements.forEach((e => e.prepend(this.templateContent)));
},
remove() {
this.targetElements.forEach((e => e.remove()));
},
replace() {
this.targetElements.forEach((e => e.replaceWith(this.templateContent)));
},
update() {
this.targetElements.forEach((targetElement => {
targetElement.innerHTML = "";
targetElement.append(this.templateContent);
}));
}
};
const session = new Session;
const cache = new Cache(session);
const {navigator: navigator$1} = session;
function start() {
session.start();
}
function registerAdapter(adapter) {
session.registerAdapter(adapter);
}
function visit(location, options) {
session.visit(location, options);
}
function connectStreamSource(source) {
session.connectStreamSource(source);
}
function disconnectStreamSource(source) {
session.disconnectStreamSource(source);
}
function renderStreamMessage(message) {
session.renderStreamMessage(message);
}
function clearCache() {
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.`");
session.clearCache();
}
function setProgressBarDelay(delay) {
session.setProgressBarDelay(delay);
}
function setConfirmMethod(confirmMethod) {
FormSubmission.confirmMethod = confirmMethod;
}
function setFormMode(mode) {
session.setFormMode(mode);
}
var Turbo = Object.freeze({
__proto__: null,
navigator: navigator$1,
session: session,
cache: cache,
PageRenderer: PageRenderer,
PageSnapshot: PageSnapshot,
FrameRenderer: FrameRenderer,
start: start,
registerAdapter: registerAdapter,
visit: visit,
connectStreamSource: connectStreamSource,
disconnectStreamSource: disconnectStreamSource,
renderStreamMessage: renderStreamMessage,
clearCache: clearCache,
setProgressBarDelay: setProgressBarDelay,
setConfirmMethod: setConfirmMethod,
setFormMode: setFormMode,
StreamActions: StreamActions
});
class TurboFrameMissingError extends Error {}
class FrameController {
constructor(element) {
this.fetchResponseLoaded = _fetchResponse => {};
this.currentFetchRequest = null;
this.resolveVisitPromise = () => {};
this.connected = false;
this.hasBeenLoaded = false;
this.ignoredAttributes = new Set;
this.action = null;
this.visitCachedSnapshot = ({element: element}) => {
const frame = element.querySelector("#" + this.element.id);
if (frame && this.previousFrameElement) {
frame.replaceChildren(...this.previousFrameElement.children);
}
delete this.previousFrameElement;
};
this.element = element;
this.view = new FrameView(this, this.element);
this.appearanceObserver = new AppearanceObserver(this, this.element);
this.formLinkClickObserver = new FormLinkClickObserver(this, this.element);
this.linkInterceptor = new LinkInterceptor(this, this.element);
this.restorationIdentifier = uuid();
this.formSubmitObserver = new FormSubmitObserver(this, this.element);
}
connect() {
if (!this.connected) {
this.connected = true;
if (this.loadingStyle == FrameLoadingStyle.lazy) {
this.appearanceObserver.start();
} else {
this.loadSourceURL();
}
this.formLinkClickObserver.start();
this.linkInterceptor.start();
this.formSubmitObserver.start();
}
}
disconnect() {
if (this.connected) {
this.connected = false;
this.appearanceObserver.stop();
this.formLinkClickObserver.stop();
this.linkInterceptor.stop();
this.formSubmitObserver.stop();
}
}
disabledChanged() {
if (this.loadingStyle == FrameLoadingStyle.eager) {
this.loadSourceURL();
}
}
sourceURLChanged() {
if (this.isIgnoringChangesTo("src")) return;
if (this.element.isConnected) {
this.complete = false;
}
if (this.loadingStyle == FrameLoadingStyle.eager || this.hasBeenLoaded) {
this.loadSourceURL();
}
}
sourceURLReloaded() {
const {src: src} = this.element;
this.ignoringChangesToAttribute("complete", (() => {
this.element.removeAttribute("complete");
}));
this.element.src = null;
this.element.src = src;
return this.element.loaded;
}
completeChanged() {
if (this.isIgnoringChangesTo("complete")) return;
this.loadSourceURL();
}
loadingStyleChanged() {
if (this.loadingStyle == FrameLoadingStyle.lazy) {
this.appearanceObserver.start();
} else {
this.appearanceObserver.stop();
this.loadSourceURL();
}
}
async loadSourceURL() {
if (this.enabled && this.isActive && !this.complete && this.sourceURL) {
this.element.loaded = this.visit(expandURL(this.sourceURL));
this.appearanceObserver.stop();
await this.element.loaded;
this.hasBeenLoaded = true;
}
}
async loadResponse(fetchResponse) {
if (fetchResponse.redirected || fetchResponse.succeeded && fetchResponse.isHTML) {
this.sourceURL = fetchResponse.response.url;
}
try {
const html = await fetchResponse.responseHTML;
if (html) {
const document = parseHTMLDocument(html);
const pageSnapshot = PageSnapshot.fromDocument(document);
if (pageSnapshot.isVisitable) {
await this.loadFrameResponse(fetchResponse, document);
} else {
await this.handleUnvisitableFrameResponse(fetchResponse);
}
}
} finally {
this.fetchResponseLoaded = () => {};
}
}
elementAppearedInViewport(element) {
this.proposeVisitIfNavigatedWithAction(element, element);
this.loadSourceURL();
}
willSubmitFormLinkToLocation(link) {
return this.shouldInterceptNavigation(link);
}
submittedFormLinkToLocation(link, _location, form) {
const frame = this.findFrameElement(link);
if (frame) form.setAttribute("data-turbo-frame", frame.id);
}
shouldInterceptLinkClick(element, _location, _event) {
return this.shouldInterceptNavigation(element);
}
linkClickIntercepted(element, location) {
this.navigateFrame(element, location);
}
willSubmitForm(element, submitter) {
return element.closest("turbo-frame") == this.element && this.shouldInterceptNavigation(element, submitter);
}
formSubmitted(element, submitter) {
if (this.formSubmission) {
this.formSubmission.stop();
}
this.formSubmission = new FormSubmission(this, element, submitter);
const {fetchRequest: fetchRequest} = this.formSubmission;
this.prepareRequest(fetchRequest);
this.formSubmission.start();
}
prepareRequest(request) {
var _a;
request.headers["Turbo-Frame"] = this.id;
if ((_a = this.currentNavigationElement) === null || _a === void 0 ? void 0 : _a.hasAttribute("data-turbo-stream")) {
request.acceptResponseType(StreamMessage.contentType);
}
}
requestStarted(_request) {
markAsBusy(this.element);
}
requestPreventedHandlingResponse(_request, _response) {
this.resolveVisitPromise();
}
async requestSucceededWithResponse(request, response) {
await this.loadResponse(response);
this.resolveVisitPromise();
}
async requestFailedWithResponse(request, response) {
await this.loadResponse(response);
this.resolveVisitPromise();
}
requestErrored(request, error) {
console.error(error);
this.resolveVisitPromise();
}
requestFinished(_request) {
clearBusyState(this.element);
}
formSubmissionStarted({formElement: formElement}) {
markAsBusy(formElement, this.findFrameElement(formElement));
}
formSubmissionSucceededWithResponse(formSubmission, response) {
const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter);
frame.delegate.proposeVisitIfNavigatedWithAction(frame, formSubmission.formElement, formSubmission.submitter);
frame.delegate.loadResponse(response);
if (!formSubmission.isSafe) {
session.clearCache();
}
}
formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
this.element.delegate.loadResponse(fetchResponse);
session.clearCache();
}
formSubmissionErrored(formSubmission, error) {
console.error(error);
}
formSubmissionFinished({formElement: formElement}) {
clearBusyState(formElement, this.findFrameElement(formElement));
}
allowsImmediateRender({element: newFrame}, options) {
const event = dispatch("turbo:before-frame-render", {
target: this.element,
detail: Object.assign({
newFrame: newFrame
}, options),
cancelable: true
});
const {defaultPrevented: defaultPrevented, detail: {render: render}} = event;
if (this.view.renderer && render) {
this.view.renderer.renderElement = render;
}
return !defaultPrevented;
}
viewRenderedSnapshot(_snapshot, _isPreview) {}
preloadOnLoadLinksForView(element) {
session.preloadOnLoadLinksForView(element);
}
viewInvalidated() {}
willRenderFrame(currentElement, _newElement) {
this.previousFrameElement = currentElement.cloneNode(true);
}
async loadFrameResponse(fetchResponse, document) {
const newFrameElement = await this.extractForeignFrameElement(document.body);
if (newFrameElement) {
const snapshot = new Snapshot(newFrameElement);
const renderer = new FrameRenderer(this, this.view.snapshot, snapshot, FrameRenderer.renderElement, false, false);
if (this.view.renderPromise) await this.view.renderPromise;
this.changeHistory();
await this.view.render(renderer);
this.complete = true;
session.frameRendered(fetchResponse, this.element);
session.frameLoaded(this.element);
this.fetchResponseLoaded(fetchResponse);
} else if (this.willHandleFrameMissingFromResponse(fetchResponse)) {
this.handleFrameMissingFromResponse(fetchResponse);
}
}
async visit(url) {
var _a;
const request = new FetchRequest(this, FetchMethod.get, url, new URLSearchParams, this.element);
(_a = this.currentFetchRequest) === null || _a === void 0 ? void 0 : _a.cancel();
this.currentFetchRequest = request;
return new Promise((resolve => {
this.resolveVisitPromise = () => {
this.resolveVisitPromise = () => {};
this.currentFetchRequest = null;
resolve();
};
request.perform();
}));
}
navigateFrame(element, url, submitter) {
const frame = this.findFrameElement(element, submitter);
frame.delegate.proposeVisitIfNavigatedWithAction(frame, element, submitter);
this.withCurrentNavigationElement(element, (() => {
frame.src = url;
}));
}
proposeVisitIfNavigatedWithAction(frame, element, submitter) {
this.action = getVisitAction(submitter, element, frame);
if (this.action) {
const pageSnapshot = PageSnapshot.fromElement(frame).clone();
const {visitCachedSnapshot: visitCachedSnapshot} = frame.delegate;
frame.delegate.fetchResponseLoaded = fetchResponse => {
if (frame.src) {
const {statusCode: statusCode, redirected: redirected} = fetchResponse;
const responseHTML = frame.ownerDocument.documentElement.outerHTML;
const response = {
statusCode: statusCode,
redirected: redirected,
responseHTML: responseHTML
};
const options = {
response: response,
visitCachedSnapshot: visitCachedSnapshot,
willRender: false,
updateHistory: false,
restorationIdentifier: this.restorationIdentifier,
snapshot: pageSnapshot
};
if (this.action) options.action = this.action;
session.visit(frame.src, options);
}
};
}
}
changeHistory() {
if (this.action) {
const method = getHistoryMethodForAction(this.action);
session.history.update(method, expandURL(this.element.src || ""), this.restorationIdentifier);
}
}
async handleUnvisitableFrameResponse(fetchResponse) {
console.warn(`The response (${fetchResponse.statusCode}) from is performing a full page visit due to turbo-visit-control.`);
await this.visitResponse(fetchResponse.response);
}
willHandleFrameMissingFromResponse(fetchResponse) {
this.element.setAttribute("complete", "");
const response = fetchResponse.response;
const visit = async (url, options = {}) => {
if (url instanceof Response) {
this.visitResponse(url);
} else {
session.visit(url, options);
}
};
const event = dispatch("turbo:frame-missing", {
target: this.element,
detail: {
response: response,
visit: visit
},
cancelable: true
});
return !event.defaultPrevented;
}
handleFrameMissingFromResponse(fetchResponse) {
this.view.missing();
this.throwFrameMissingError(fetchResponse);
}
throwFrameMissingError(fetchResponse) {
const message = `The response (${fetchResponse.statusCode}) did not contain the expected and will be ignored. To perform a full page visit instead, set turbo-visit-control to reload.`;
throw new TurboFrameMissingError(message);
}
async visitResponse(response) {
const wrapped = new FetchResponse(response);
const responseHTML = await wrapped.responseHTML;
const {location: location, redirected: redirected, statusCode: statusCode} = wrapped;
return session.visit(location, {
response: {
redirected: redirected,
statusCode: statusCode,
responseHTML: responseHTML
}
});
}
findFrameElement(element, submitter) {
var _a;
const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target");
return (_a = getFrameElementById(id)) !== null && _a !== void 0 ? _a : this.element;
}
async extractForeignFrameElement(container) {
let element;
const id = CSS.escape(this.id);
try {
element = activateElement(container.querySelector(`turbo-frame#${id}`), this.sourceURL);
if (element) {
return element;
}
element = activateElement(container.querySelector(`turbo-frame[src][recurse~=${id}]`), this.sourceURL);
if (element) {
await element.loaded;
return await this.extractForeignFrameElement(element);
}
} catch (error) {
console.error(error);
return new FrameElement;
}
return null;
}
formActionIsVisitable(form, submitter) {
const action = getAction(form, submitter);
return locationIsVisitable(expandURL(action), this.rootLocation);
}
shouldInterceptNavigation(element, submitter) {
const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target");
if (element instanceof HTMLFormElement && !this.formActionIsVisitable(element, submitter)) {
return false;
}
if (!this.enabled || id == "_top") {
return false;
}
if (id) {
const frameElement = getFrameElementById(id);
if (frameElement) {
return !frameElement.disabled;
}
}
if (!session.elementIsNavigatable(element)) {
return false;
}
if (submitter && !session.elementIsNavigatable(submitter)) {
return false;
}
return true;
}
get id() {
return this.element.id;
}
get enabled() {
return !this.element.disabled;
}
get sourceURL() {
if (this.element.src) {
return this.element.src;
}
}
set sourceURL(sourceURL) {
this.ignoringChangesToAttribute("src", (() => {
this.element.src = sourceURL !== null && sourceURL !== void 0 ? sourceURL : null;
}));
}
get loadingStyle() {
return this.element.loading;
}
get isLoading() {
return this.formSubmission !== undefined || this.resolveVisitPromise() !== undefined;
}
get complete() {
return this.element.hasAttribute("complete");
}
set complete(value) {
this.ignoringChangesToAttribute("complete", (() => {
if (value) {
this.element.setAttribute("complete", "");
} else {
this.element.removeAttribute("complete");
}
}));
}
get isActive() {
return this.element.isActive && this.connected;
}
get rootLocation() {
var _a;
const meta = this.element.ownerDocument.querySelector(`meta[name="turbo-root"]`);
const root = (_a = meta === null || meta === void 0 ? void 0 : meta.content) !== null && _a !== void 0 ? _a : "/";
return expandURL(root);
}
isIgnoringChangesTo(attributeName) {
return this.ignoredAttributes.has(attributeName);
}
ignoringChangesToAttribute(attributeName, callback) {
this.ignoredAttributes.add(attributeName);
callback();
this.ignoredAttributes.delete(attributeName);
}
withCurrentNavigationElement(element, callback) {
this.currentNavigationElement = element;
callback();
delete this.currentNavigationElement;
}
}
function getFrameElementById(id) {
if (id != null) {
const element = document.getElementById(id);
if (element instanceof FrameElement) {
return element;
}
}
}
function activateElement(element, currentURL) {
if (element) {
const src = element.getAttribute("src");
if (src != null && currentURL != null && urlsAreEqual(src, currentURL)) {
throw new Error(`Matching element has a source URL which references itself`);
}
if (element.ownerDocument !== document) {
element = document.importNode(element, true);
}
if (element instanceof FrameElement) {
element.connectedCallback();
element.disconnectedCallback();
return element;
}
}
}
class StreamElement extends HTMLElement {
static async renderElement(newElement) {
await newElement.performAction();
}
async connectedCallback() {
try {
await this.render();
} catch (error) {
console.error(error);
} finally {
this.disconnect();
}
}
async render() {
var _a;
return (_a = this.renderPromise) !== null && _a !== void 0 ? _a : this.renderPromise = (async () => {
const event = this.beforeRenderEvent;
if (this.dispatchEvent(event)) {
await nextAnimationFrame();
await event.detail.render(this);
}
})();
}
disconnect() {
try {
this.remove();
} catch (_a) {}
}
removeDuplicateTargetChildren() {
this.duplicateChildren.forEach((c => c.remove()));
}
get duplicateChildren() {
var _a;
const existingChildren = this.targetElements.flatMap((e => [ ...e.children ])).filter((c => !!c.id));
const newChildrenIds = [ ...((_a = this.templateContent) === null || _a === void 0 ? void 0 : _a.children) || [] ].filter((c => !!c.id)).map((c => c.id));
return existingChildren.filter((c => newChildrenIds.includes(c.id)));
}
get performAction() {
if (this.action) {
const actionFunction = StreamActions[this.action];
if (actionFunction) {
return actionFunction;
}
this.raise("unknown action");
}
this.raise("action attribute is missing");
}
get targetElements() {
if (this.target) {
return this.targetElementsById;
} else if (this.targets) {
return this.targetElementsByQuery;
} else {
this.raise("target or targets attribute is missing");
}
}
get templateContent() {
return this.templateElement.content.cloneNode(true);
}
get templateElement() {
if (this.firstElementChild === null) {
const template = this.ownerDocument.createElement("template");
this.appendChild(template);
return template;
} else if (this.firstElementChild instanceof HTMLTemplateElement) {
return this.firstElementChild;
}
this.raise("first child element must be a element");
}
get action() {
return this.getAttribute("action");
}
get target() {
return this.getAttribute("target");
}
get targets() {
return this.getAttribute("targets");
}
raise(message) {
throw new Error(`${this.description}: ${message}`);
}
get description() {
var _a, _b;
return (_b = ((_a = this.outerHTML.match(/<[^>]+>/)) !== null && _a !== void 0 ? _a : [])[0]) !== null && _b !== void 0 ? _b : "";
}
get beforeRenderEvent() {
return new CustomEvent("turbo:before-stream-render", {
bubbles: true,
cancelable: true,
detail: {
newStream: this,
render: StreamElement.renderElement
}
});
}
get targetElementsById() {
var _a;
const element = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.getElementById(this.target);
if (element !== null) {
return [ element ];
} else {
return [];
}
}
get targetElementsByQuery() {
var _a;
const elements = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.querySelectorAll(this.targets);
if (elements.length !== 0) {
return Array.prototype.slice.call(elements);
} else {
return [];
}
}
}
class StreamSourceElement extends HTMLElement {
constructor() {
super(...arguments);
this.streamSource = null;
}
connectedCallback() {
this.streamSource = this.src.match(/^ws{1,2}:/) ? new WebSocket(this.src) : new EventSource(this.src);
connectStreamSource(this.streamSource);
}
disconnectedCallback() {
if (this.streamSource) {
disconnectStreamSource(this.streamSource);
}
}
get src() {
return this.getAttribute("src") || "";
}
}
FrameElement.delegateConstructor = FrameController;
if (customElements.get("turbo-frame") === undefined) {
customElements.define("turbo-frame", FrameElement);
}
if (customElements.get("turbo-stream") === undefined) {
customElements.define("turbo-stream", StreamElement);
}
if (customElements.get("turbo-stream-source") === undefined) {
customElements.define("turbo-stream-source", StreamSourceElement);
}
(() => {
let element = document.currentScript;
if (!element) return;
if (element.hasAttribute("data-turbo-suppress-warning")) return;
element = element.parentElement;
while (element) {
if (element == document.body) {
return console.warn(unindent`
You are loading Turbo from a