-
Notifications
You must be signed in to change notification settings - Fork 430
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
Morphing between different URLs #1177
Comments
pch
added a commit
to pch/turbo
that referenced
this issue
Feb 8, 2024
Allows morphing between similar types of pages that have different URLs. A proof of concept fix for the problem descrubed here: hotwired#1177 For example, if you set this meta tag: <meta name="turbo-morph-url-prefix" content="/images/"> Then morphing will be triggered for: - `/images/1` - `/images/12` - `/images/123` This solution has some downsides (e.g, won't work with nested resources). A regex-based alternative could address that. Please let me know if you'd be willing to consider this change and I'll go ahead and add tests.
This was referenced Feb 8, 2024
@pch I think turbo-frames solve your situation. If you put the center column (or center + right column) within it's own This way the left column retains it's scroll position because only the |
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Mar 30, 2024
Follow-up to [][] Related to [hotwired#1192][] The `morphElements` function --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement, delegate)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `Morph` class. The `Morph` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `Morph` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a delegate responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `PageMorphRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `FrameMorphRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `PageMorphRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `PageMorphRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `PageMorphRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `FrameMorphRenderer` class to define the `FrameMorphRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = (currentElement, newElement) => { window.Turbo.morphElements(currentElement, newElement, { ... }) } } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Mar 30, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morphElements` function --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement, delegate)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `Morph` class. The `Morph` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `Morph` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a delegate responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `PageMorphRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `FrameMorphRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `PageMorphRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `PageMorphRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `PageMorphRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `FrameMorphRenderer` class to define the `FrameMorphRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = (currentElement, newElement) => { window.Turbo.morphElements(currentElement, newElement, { ... }) } } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Mar 30, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morphElements` function --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement, delegate)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphDelegate` class. The `IdomorphDelegate` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphDelegate` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a delegate responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `PageMorphRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `FrameMorphRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `PageMorphRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `PageMorphRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `PageMorphRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `FrameMorphRenderer` class to define the `FrameMorphRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = (currentElement, newElement) => { window.Turbo.morphElements(currentElement, newElement, { ... }) } } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Mar 30, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morphElements` function --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement, delegate)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphDelegate` class. The `IdomorphDelegate` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphDelegate` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a delegate responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `PageMorphRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `FrameMorphRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `PageMorphRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `PageMorphRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `PageMorphRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `FrameMorphRenderer` class to define the `FrameMorphRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][hotwired#1177] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = (currentElement, newElement) => { window.Turbo.morphElements(currentElement, newElement, { ... }) } } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Mar 30, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morphElements` function --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement, delegate)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphDelegate` class. The `IdomorphDelegate` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphDelegate` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a delegate responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `PageMorphRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `FrameMorphRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `PageMorphRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `PageMorphRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `PageMorphRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `FrameMorphRenderer` class to define the `FrameMorphRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][hotwired#1177] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = (currentElement, newElement) => { window.Turbo.morphElements(currentElement, newElement, { ... }) } } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Apr 3, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morphElements` function --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement, delegate)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphDelegate` class. The `IdomorphDelegate` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphDelegate` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a delegate responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `PageMorphRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `FrameMorphRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `PageMorphRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `PageMorphRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `PageMorphRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `FrameMorphRenderer` class to define the `FrameMorphRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][hotwired#1177] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = (currentElement, newElement) => { window.Turbo.morphElements(currentElement, newElement, { ... }) } } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Apr 8, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morphElements` function --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement, delegate)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphDelegate` class. The `IdomorphDelegate` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphDelegate` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a delegate responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `PageMorphRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `FrameMorphRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `PageMorphRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `PageMorphRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `PageMorphRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `FrameMorphRenderer` class to define the `FrameMorphRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][hotwired#1177] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = (currentElement, newElement) => { window.Turbo.morphElements(currentElement, newElement, { ... }) } } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Apr 8, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morphElements` function --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement, delegate)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphDelegate` class. The `IdomorphDelegate` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphDelegate` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a delegate responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `PageMorphRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `FrameMorphRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `PageMorphRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `PageMorphRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `PageMorphRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `FrameMorphRenderer` class to define the `FrameMorphRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][hotwired#1177] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = (currentElement, newElement) => { window.Turbo.morphElements(currentElement, newElement, { ... }) } } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Apr 13, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morph{Page,Frames,Elements}` functions --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphCallbacks` class. The `IdomorphCallbacks` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphCallbacks` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a callback responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `MorphingPageRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `MorphingFrameRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `MorphingPageRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `MorphingPageRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `MorphingPageRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `MorphingFrameRenderer` class to define the `MorphingFrameRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][hotwired#1177] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = Turbo.morphPage } }) addEventListener("turbo:before-frame-render", (event) => { const someCriteriaForMorphingAFrame = ... if (someCriteriaForMorphingAFrame) { event.detail.render = Turbo.morphFrames } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Apr 15, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morph{Page,Frames,Elements}` functions --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphCallbacks` class. The `IdomorphCallbacks` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphCallbacks` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a callback responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `MorphingPageRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `MorphingFrameRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `MorphingPageRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `MorphingPageRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `MorphingPageRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `MorphingFrameRenderer` class to define the `MorphingFrameRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][hotwired#1177] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = Turbo.morphPage } }) addEventListener("turbo:before-frame-render", (event) => { const someCriteriaForMorphingAFrame = ... if (someCriteriaForMorphingAFrame) { event.detail.render = Turbo.morphFrames } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Apr 15, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morph{Page,Frames,Elements}` functions --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphCallbacks` class. The `IdomorphCallbacks` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphCallbacks` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a callback responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `MorphingPageRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `MorphingFrameRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `MorphingPageRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `MorphingPageRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `MorphingPageRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `MorphingFrameRenderer` class to define the `MorphingFrameRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][hotwired#1177] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = Turbo.morphPage } }) addEventListener("turbo:before-frame-render", (event) => { const someCriteriaForMorphingAFrame = ... if (someCriteriaForMorphingAFrame) { event.detail.render = Turbo.morphFrames } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Apr 15, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morph{Page,Frames,Elements}` functions --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphCallbacks` class. The `IdomorphCallbacks` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphCallbacks` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a callback responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `MorphingPageRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `MorphingFrameRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `MorphingPageRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `MorphingPageRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `MorphingPageRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `MorphingFrameRenderer` class to define the `MorphingFrameRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][hotwired#1177] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = Turbo.morphPage } }) addEventListener("turbo:before-frame-render", (event) => { const someCriteriaForMorphingAFrame = ... if (someCriteriaForMorphingAFrame) { event.detail.render = Turbo.morphFrames } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
seanpdoyle
added a commit
to seanpdoyle/turbo
that referenced
this issue
Jul 3, 2024
Follow-up to [hotwired#1185][] Related to [hotwired#1192][] The `morph{Page,Frames,Elements}` functions --- Introduce a new `src/core/morphing` module to expose a centralized and re-usable `morphElements(currentElement, newElement)` function to be invoked across the various morphing contexts. Next, move the logic from the `MorphRenderer` into a module-private `IdomorphCallbacks` class. The `IdomorphCallbacks` class (like its `MorphRenderer` predecessor) wraps a call to `Idiomorph` based on its own set of callbacks. The bulk of the logic remains in the `IdomorphCallbacks` class, including checks for `[data-turbo-permanent]`. To serve as a seam for integration, the class retains a reference to a callback responsible for: * providing options for the `Idiomorph` * determining whether or not a node should be skipped while morphing The `MorphingPageRenderer` skips `<turbo-frame refresh="morph">` elements so that it can override their rendering to use morphing. Similarly, the `MorphingFrameRenderer` provides the `morphStyle: "innerHTML"` option to morph its children. Changes to the renderers --- To integrate with the new module, first rename the `MorphRenderer` to `MorphingPageRenderer` to set a new precedent that communicates the level of the document the morphing is scoped to. With that change in place, define the static `MorphingPageRenderer.renderElement` to mirror the other existing renderer static functions (like [PageRenderer.renderElement][], [ErrorRenderer.renderElement][], and [FrameRenderer.renderElement][]). This integrates with the changes proposed in [hotwired#1028][]. Next, modify the rest of the `MorphingPageRenderer` to integrate with its `PageRenderer` ancestor in a way that invokes the static `renderElement` function. This involves overriding the `preservingPermanentElements(callback)` method. In theory, morphing has implications on the concept of "permanence". In practice, morphing has the `[data-turbo-permanent]` attribute receive special treatment during morphing. Following the new precedent, introduce a new `MorphingFrameRenderer` class to define the `MorphingFrameRenderer.renderElement` function that invokes the `morphElements` function with `newElement.children` and `morphStyle: "innerHTML"`. Changes to the StreamActions --- The extraction of the `morphElements` function makes entirety of the `src/core/streams/actions/morph.js` module redundant. This commit removes that module and invokes `morphElements` directly within the `StreamActions.morph` function. Future possibilities --- In the future, additional changes could be made to expose the morphing capabilities as part of the `window.Turbo` interface. For example, applications could experiment with supporting [Page Refresh-style morphing for pages with different URL pathnames][hotwired#1177] by overriding the rendering mechanism in `turbo:before-render`: ```js addEventListener("turbo:before-render", (event) => { const someCriteriaForMorphing = ... if (someCriteriaForMorphing) { event.detail.render = Turbo.morphPage } }) addEventListener("turbo:before-frame-render", (event) => { const someCriteriaForMorphingAFrame = ... if (someCriteriaForMorphingAFrame) { event.detail.render = Turbo.morphFrames } }) ``` [hotwired#1185]: hotwired#1185 (comment) [hotwired#1192]: hotwired#1192 [PageRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/page_renderer.js#L5-L11 [ErrorRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/drive/error_renderer.js#L5-L9 [FrameRenderer.renderElement]: https://github.com/hotwired/turbo/blob/9fb05e3ed3ebb15fe7b13f52941f25df425e3d15/src/core/frames/frame_renderer.js#L5-L16 [hotwired#1028]: hotwired#1028 [hotwired#1177]: hotwired#1177
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There's a scenario where I think morphing could be useful between different URLs.
Consider the following example (a 9mb gif screen recording below):
Let's say we have an image browser like the one above. The page structure is basically the same, only certain parts change when you select a different image. Because each image has a unique URL, morphing doesn't apply and scrollbars reset.
In this case, it would be great to be able to set something like
<meta name="turbo-page-id" content="images#show">
and have Turbo use it to apply morphing between different URLs.The text was updated successfully, but these errors were encountered: