Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid bubbling form submissions that target a new window/tab #755

Closed
wants to merge 6 commits into from
Closed

Avoid bubbling form submissions that target a new window/tab #755

wants to merge 6 commits into from

Conversation

martinzamuner
Copy link

Resolves #754

Avoid bubbling <form> element submissions when they target a new window/tab. This occurs when:

  • a <form> declares a target of _blank
  • a <form> element's submitting <button> element declares a formtarget of _blank
  • a <form> element's submitting <input type="submit"> element declares a formtarget of _blank

Based on #389

@seanpdoyle
Copy link
Contributor

@martinzamuner thank you for proposing this change!

When I'd proposed the submissionDoesNotTargetIFrame method, I'd forgotten about _blank:

function submissionDoesNotTargetIFrame(form: HTMLFormElement, submitter?: HTMLElement): boolean {
const target = submitter?.getAttribute("formtarget") || form.target
for (const element of document.getElementsByName(target)) {
if (element instanceof HTMLIFrameElement) return false
}
return true
}

Instead of adding a new method, what do you think about combining submissionDoesNotTargetIFrame and submissionDoesNotTargetBlankWindow so that it checks for the presence of any [target] on the <form> or [formtarget] on the submitter?

Similarly, could you add coverage for the same scenario for <a> elements and make similar changes to the LinkClickObserver?

function doesNotTargetIFrame(anchor: HTMLAnchorElement): boolean {
for (const element of document.getElementsByName(anchor.target)) {
if (element instanceof HTMLIFrameElement) return false
}
return true
}
?


return true
function doesNotHaveSpecificTarget(anchor: HTMLAnchorElement): boolean {
return anchor.target != "_self"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to have a special case handler for _self, could we also add test coverage to guarantee that behavior and guard against regressions?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! BTW, I had to remove the check on target from LinkClickObserver#findLinkFromClickTarget to avoid a full-page load in the case of [target=_self].

@martinzamuner
Copy link
Author

@seanpdoyle Sure thing! I've added a special case for _self, which I think should behave the same as having no target. Let me know if you think this is unnecessary.

There was already a test for this behavior with anchors: https://github.com/hotwired/turbo/blob/main/src/tests/functional/navigation_tests.ts#L208-L213.

@martinzamuner
Copy link
Author

@dhh Thanks for running the tests! There were a couple failures related to anchors inside SVGs behaving kind of weird. Their target is implemented through an SVGAnimatedString, which I didn't know. Using the getAttribute function fixed those.

Aside from that, those same tests were now broken because I added some elements before the SVGs in the fixture, and they were not above the fold anymore. That means that page.click would have to scroll to the anchors inside, but was failing to do so. I'm not exactly sure why (maybe something to do with this)? My solution was to scroll to the next element before attempting the click. It's not very elegant, though. Suggestions are welcomed.

@martinzamuner
Copy link
Author

Fixed by #835.

@martinzamuner martinzamuner deleted the submitting-form-with-target-blank branch October 30, 2023 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Submitting a form with [target=_blank] ignores the target
2 participants