diff --git a/src/core/drive/navigator.ts b/src/core/drive/navigator.ts index 6b87a3126..59b2ad0e1 100644 --- a/src/core/drive/navigator.ts +++ b/src/core/drive/navigator.ts @@ -3,6 +3,7 @@ import { FetchMethod } from "../../http/fetch_request" import { FetchResponse } from "../../http/fetch_response" import { FormSubmission } from "./form_submission" import { expandURL, getAnchor, getRequestURL, Locatable, locationIsVisitable } from "../url" +import { getAttribute } from "../../util" import { Visit, VisitDelegate, VisitOptions } from "./visit" import { PageSnapshot } from "./page_snapshot" @@ -158,7 +159,7 @@ export class Navigator { getActionForFormSubmission(formSubmission: FormSubmission): Action { const { formElement, submitter } = formSubmission - const action = submitter?.getAttribute("data-turbo-action") || formElement.getAttribute("data-turbo-action") + const action = getAttribute("data-turbo-action", submitter, formElement) return isAction(action) ? action : "advance" } } diff --git a/src/core/frames/frame_controller.ts b/src/core/frames/frame_controller.ts index 6f11438ee..b92246fbc 100644 --- a/src/core/frames/frame_controller.ts +++ b/src/core/frames/frame_controller.ts @@ -2,7 +2,7 @@ import { FrameElement, FrameElementDelegate, FrameLoadingStyle } from "../../ele import { FetchMethod, FetchRequest, FetchRequestDelegate, FetchRequestHeaders } from "../../http/fetch_request" import { FetchResponse } from "../../http/fetch_response" import { AppearanceObserver, AppearanceObserverDelegate } from "../../observers/appearance_observer" -import { parseHTMLDocument } from "../../util" +import { getAttribute, parseHTMLDocument } from "../../util" import { FormSubmission, FormSubmissionDelegate } from "../drive/form_submission" import { Snapshot } from "../snapshot" import { ViewDelegate } from "../view" @@ -259,7 +259,7 @@ export class FrameController implements AppearanceObserverDelegate, FetchRequest } private proposeVisitIfNavigatedWithAction(frame: FrameElement, element: Element, submitter?: HTMLElement) { - const action = submitter?.getAttribute("data-turbo-action") || element.getAttribute("data-turbo-action") || frame.getAttribute("data-turbo-action") + const action = getAttribute("data-turbo-action", submitter, element, frame) if (isAction(action)) { const proposeVisit = async (event: Event) => { @@ -274,7 +274,7 @@ export class FrameController implements AppearanceObserverDelegate, FetchRequest } private findFrameElement(element: Element, submitter?: HTMLElement) { - const id = submitter?.getAttribute("data-turbo-frame") || element.getAttribute("data-turbo-frame") || this.element.getAttribute("target") + const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target") return getFrameElementById(id) ?? this.element } @@ -301,7 +301,7 @@ export class FrameController implements AppearanceObserverDelegate, FetchRequest } private shouldInterceptNavigation(element: Element, submitter?: Element) { - const id = submitter?.getAttribute("data-turbo-frame") || element.getAttribute("data-turbo-frame") || this.element.getAttribute("target") + const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target") if (!this.enabled || id == "_top") { return false diff --git a/src/util.ts b/src/util.ts index 5b873e404..5cef3785b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -55,3 +55,11 @@ export function uuid() { } }).join("") } + +export function getAttribute(attributeName: string, ...elements: (Element | undefined)[]): string | null { + for (const value of elements.map(element => element?.getAttribute(attributeName))) { + if (typeof value == "string") return value + } + + return null +}