hotwired / turbo

The speed of a single-page web application without having to write any JavaScript
https://turbo.hotwired.dev
MIT License
6.73k stars 429 forks source link

Turbo visit breaks iOS Time and Date Inputs/keyboards #173

Open senordelaflor opened 3 years ago

senordelaflor commented 3 years ago

We have recently replaced Turbolinks with Turbo and got a bug report from a client telling us that the dates and times were not displaying properly in Safari. We have tested this under iOS 14 ourselves and have confirmed that something that Turbo does prevents Safari from loading the special time and date keyboards as well as the formatting done by safari natively.

Input type="time" after Turbo visit:

CleanShot 2021-02-11 at 12 16 07

Input type="time" after non-Turbo visit:

CleanShot 2021-02-11 at 12 19 32

As can be seen in the videos above, when not using Turbo, Safari displays the time and keyboard correctly (this also applies for <input type="date">).

When using Turbo, however, the native keyboards/time display changes no longer work.

For additional context, the inputs worked as expected with Turbolinks.

For now, we have resorted to disabling Turbo on the links that lead to the page with the form, but it would be great to have someone from the Turbo team take a look at this, if possible.

As a side note: Is there a way to force Turbo to reload a page? I know that for Turbolinks we had the <meta name="turbolinks-visit-control" content="reload" flag, but I cannot find something similar for Turbo. Currently, if a user navigates to the page with the <input type="time"> with the browser back and forth buttons, they'll see the broken time inputs for a few seconds and they correct themselves after the page is loaded.

Thank you.

thewatts commented 3 years ago

I've made a sample app to demonstrate this issue, that doesn't use webpacker, etc.

It can be found here: https://github.com/thewatts/sample-app-turbo-ios

Thanks for your incredible work on Hotwire!

https://user-images.githubusercontent.com/1141717/107684110-00c15180-6c68-11eb-91a4-dbdbe32b01fb.mp4

thewatts commented 3 years ago

Also, wanted to point out that - when Turbo is running, the browser fails to update the input from being 24-hour-time to regular time (am/pm).

This is how we ultimately stumbled upon this issue.

javan commented 3 years ago

Thanks for the report! I’ve narrowed this down to a Safari bug with document.adoptNode() and filed a report upstream: https://bugs.webkit.org/show_bug.cgi?id=222657.

The bug comes into play here https://github.com/hotwired/turbo/blob/8bce5f17cd697716600d3b34836365ebcdc04b3f/src/core/drive/page_renderer.ts#L78-L79 and is a result of changes introduced (by me) in a previous private fork of Turbo, which I’ll share below.

Summary ![Screen Shot 2021-03-03 120258](https://user-images.githubusercontent.com/5355/109843170-c6b8ef00-7c18-11eb-9b82-87e2544b14dd.png)
Initial diff ```diff diff --git a/src/snapshot.ts b/src/snapshot.ts index 5987ff5..4d5ad0c 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -14,9 +14,8 @@ export class Snapshot { } static fromHTMLString(html: string) { - const element = document.createElement("html") - element.innerHTML = html - return this.fromHTMLElement(element) + const { documentElement } = new DOMParser().parseFromString(html, "text/html") + return this.fromHTMLElement(documentElement as HTMLHtmlElement) } static fromHTMLElement(htmlElement: HTMLHtmlElement) { @@ -35,7 +34,8 @@ export class Snapshot { } clone(): Snapshot { - return new Snapshot(this.headDetails, this.bodyElement.cloneNode(true)) + const { bodyElement } = Snapshot.fromHTMLString(this.bodyElement.outerHTML) + return new Snapshot(this.headDetails, bodyElement) } getRootLocation() { ```