From f8d95b1a1ee669a9a96d111fcb2c8a920956c894 Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Tue, 30 Jan 2024 13:27:36 -0500 Subject: [PATCH] Morph with `ignoreActiveValue: true` (#1141) * Morph with `ignoreActiveValue: true` Morph with the [ignoreActiveValue: true][] option to morph the currently focused element's attributes, but preserve its value. This behavior can be extremely helpful when paired with an auto-submitting `
` element, like a typeahead `[role="combobox"]`, or an auto-submitting [``][search]. This commit depends on a fork of `idiomorph` that [fixes a bug related to `ignoreActiveValue: true`][bigskysoftware/idiomorph#34]. [ignoreActiveValue: true]: https://github.com/bigskysoftware/idiomorph#options [search]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/search [bigskysoftware/idiomorph#34]: https://github.com/bigskysoftware/idiomorph/pull/34 * Depend on latest `idiomorph` --- package.json | 2 +- src/core/drive/morph_renderer.js | 1 + src/tests/fixtures/page_refresh.html | 7 ++++++ src/tests/functional/page_refresh_tests.js | 25 +++++++++++++++++++--- yarn.lock | 5 ++--- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 1db81757f..db89cd72f 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "chai": "~4.3.4", "eslint": "^8.13.0", "express": "^4.18.2", - "idiomorph": "^0.3.0", + "idiomorph": "https://github.com/bigskysoftware/idiomorph.git", "multer": "^1.4.2", "rollup": "^2.35.1" }, diff --git a/src/core/drive/morph_renderer.js b/src/core/drive/morph_renderer.js index 87401ee23..4c25246a1 100644 --- a/src/core/drive/morph_renderer.js +++ b/src/core/drive/morph_renderer.js @@ -29,6 +29,7 @@ export class MorphRenderer extends Renderer { this.isMorphingTurboFrame = this.#isFrameReloadedWithMorph(currentElement) Idiomorph.morph(currentElement, newElement, { + ignoreActiveValue: true, morphStyle: morphStyle, callbacks: { beforeNodeAdded: this.#shouldAddElement, diff --git a/src/tests/fixtures/page_refresh.html b/src/tests/fixtures/page_refresh.html index f7f577d56..6a9cc4b5e 100644 --- a/src/tests/fixtures/page_refresh.html +++ b/src/tests/fixtures/page_refresh.html @@ -88,6 +88,13 @@

Element with Stimulus controller

+ + + +

Link with params to refresh the page

Link to another page

diff --git a/src/tests/functional/page_refresh_tests.js b/src/tests/functional/page_refresh_tests.js index 9db411665..ead9247b0 100644 --- a/src/tests/functional/page_refresh_tests.js +++ b/src/tests/functional/page_refresh_tests.js @@ -7,7 +7,8 @@ import { nextEventNamed, nextEventOnTarget, noNextEventOnTarget, - noNextEventNamed + noNextEventNamed, + getSearchParam } from "../helpers/page" test("renders a page refresh with morphing", async ({ page }) => { @@ -81,6 +82,24 @@ test("renders a page refresh with morphing when the paths are the same but searc await nextEventNamed(page, "turbo:render", { renderMethod: "morph" }) }) +test("renders a page refresh with morphing when the GET form paths are the same but search params are diferent", async ({ page }) => { + await page.goto("/src/tests/fixtures/page_refresh.html") + + const input = page.locator("form[method=get] input[name=query]") + + await input.fill("Search") + await nextEventNamed(page, "turbo:render", { renderMethod: "morph" }) + + await expect(input).toBeFocused() + expect(getSearchParam(page.url(), "query")).toEqual("Search") + + await input.press("?") + await nextEventNamed(page, "turbo:render", { renderMethod: "morph" }) + + await expect(input).toBeFocused() + expect(getSearchParam(page.url(), "query")).toEqual("Search?") +}) + test("doesn't morph when the turbo-refresh-method meta tag is not 'morph'", async ({ page }) => { await page.goto("/src/tests/fixtures/page_refresh_replace.html") @@ -181,12 +200,12 @@ test("it preserves focus across morphs", async ({ page }) => { const input = await page.locator("#form input[type=text]") - await input.fill("Discard me") + await input.fill("Preserve me") await input.press("Enter") await nextEventNamed(page, "turbo:render", { renderMethod: "morph" }) await expect(input).toBeFocused() - await expect(input).toHaveValue("") + await expect(input).toHaveValue("Preserve me") }) test("it preserves focus and the [data-turbo-permanent] element's value across morphs", async ({ page }) => { diff --git a/yarn.lock b/yarn.lock index 45b1ad28f..48b78418d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1865,10 +1865,9 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -idiomorph@^0.3.0: +"idiomorph@https://github.com/bigskysoftware/idiomorph.git": version "0.3.0" - resolved "https://registry.yarnpkg.com/idiomorph/-/idiomorph-0.3.0.tgz#f6675bc5bef1a72c94021e43141a3f605d2d6288" - integrity sha512-UhV1Ey5xCxIwR9B+OgIjQa+1Jx99XQ1vQHUsKBU1RpQzCx1u+b+N6SOXgf5mEJDqemUI/ffccu6+71l2mJUsRA== + resolved "https://github.com/bigskysoftware/idiomorph.git#b5115add9f7ab04c04af0624385540dff04e0735" ieee754@^1.1.13: version "1.2.1"