diff --git a/src/core/confirmation.js b/src/core/confirmation.js new file mode 100644 index 000000000..d78cad82b --- /dev/null +++ b/src/core/confirmation.js @@ -0,0 +1,5 @@ +export class Confirmation { + static confirmMethod(message, _element, _submitter) { + return Promise.resolve(confirm(message)) + } +} diff --git a/src/core/drive/form_submission.js b/src/core/drive/form_submission.js index c2ac1a0db..54bc77760 100644 --- a/src/core/drive/form_submission.js +++ b/src/core/drive/form_submission.js @@ -1,3 +1,4 @@ +import { Confirmation } from "../confirmation" import { FetchRequest, FetchMethod, fetchMethodFromString, fetchEnctypeFromString, isSafe } from "../../http/fetch_request" import { expandURL } from "../url" import { clearBusyState, dispatch, getAttribute, getMetaContent, hasAttribute, markAsBusy } from "../../util" @@ -22,10 +23,6 @@ export const FormEnctype = { export class FormSubmission { state = FormSubmissionState.initialized - static confirmMethod(message, _element, _submitter) { - return Promise.resolve(confirm(message)) - } - constructor(delegate, formElement, submitter, mustRedirect = false) { const method = getMethod(formElement, submitter) const action = getAction(getFormAction(formElement, submitter), method) @@ -78,7 +75,7 @@ export class FormSubmission { const confirmationMessage = getAttribute("data-turbo-confirm", this.submitter, this.formElement) if (typeof confirmationMessage === "string") { - const answer = await FormSubmission.confirmMethod(confirmationMessage, this.formElement, this.submitter) + const answer = await Confirmation.confirmMethod(confirmationMessage, this.formElement, this.submitter) if (!answer) { return } diff --git a/src/core/index.js b/src/core/index.js index a4a4f2d23..1d34e45df 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -2,7 +2,7 @@ import { Session } from "./session" import { PageRenderer } from "./drive/page_renderer" import { PageSnapshot } from "./drive/page_snapshot" import { FrameRenderer } from "./frames/frame_renderer" -import { FormSubmission } from "./drive/form_submission" +import { Confirmation } from "./confirmation" import { fetch, recentRequests } from "../http/fetch" const session = new Session(recentRequests) @@ -101,7 +101,7 @@ export function setProgressBarDelay(delay) { } export function setConfirmMethod(confirmMethod) { - FormSubmission.confirmMethod = confirmMethod + Confirmation.confirmMethod = confirmMethod } export function setFormMode(mode) { diff --git a/src/core/session.js b/src/core/session.js index cdb978348..a4fc0b7e5 100644 --- a/src/core/session.js +++ b/src/core/session.js @@ -18,6 +18,7 @@ import { PageView } from "./drive/page_view" import { FrameElement } from "../elements/frame_element" import { Preloader } from "./drive/preloader" import { Cache } from "./cache" +import { Confirmation } from "./confirmation" export class Session { navigator = new Navigator(this) @@ -223,9 +224,17 @@ export class Session { ) } - followedLinkToLocation(link, location) { + async followedLinkToLocation(link, location) { const action = this.getActionForLink(link) const acceptsStreamResponse = link.hasAttribute("data-turbo-stream") + const confirmationMessage = link.getAttribute("data-turbo-confirm") + + if (typeof confirmationMessage === "string") { + const answer = await Confirmation.confirmMethod(confirmationMessage, link, link) + if (!answer) { + return + } + } this.visit(location.href, { action, acceptsStreamResponse }) } diff --git a/src/tests/functional/visit_tests.js b/src/tests/functional/visit_tests.js index 782871747..174d922a1 100644 --- a/src/tests/functional/visit_tests.js +++ b/src/tests/functional/visit_tests.js @@ -267,6 +267,31 @@ test("Turbo history state after a reload", async ({ page }) => { ) }) +test("test data-turbo-confirm on anchor element without data-turbo-method", async ({ page }) => { + let confirmed = false + + page.on("dialog", (alert) => { + assert.equal(alert.message(), "Are you sure?") + alert.accept() + confirmed = true + }) + + await page.evaluate(() => { + const link = document.querySelector("#same-origin-link") + + if (link) link.dataset.turboConfirm = "Are you sure?" + }) + + assert.equal(await page.locator("#same-origin-link[data-turbo-confirm]:not([data-turbo-method])").count(), 1) + assert.equal(pathname(page.url()), "/src/tests/fixtures/visit.html") + + await page.click("#same-origin-link") + await nextEventNamed(page, "turbo:load") + + assert.isTrue(confirmed) + assert.equal(pathname(page.url()), "/src/tests/fixtures/one.html") +}) + async function visitLocation(page, location) { return page.evaluate((location) => window.Turbo.visit(location), location) }