https://htmx.org logo
I went down a rabbit hole and didn't like what I f...
# htmx-general
h
I went down a rabbit hole and didn't like what I found. Any insight here would be very welcome: https://github.com/bigskysoftware/htmx/issues/1076#issuecomment-1279732194
m
This is in mobile safari only, correct?
I have some free time in the next few weeks and I can do a deep dive on it, and I already don't have hair, so all good
h
Thank you. Yes you are correct, Safari on iOS. I’m reasonably sure that it’s the >500ms between user interaction (clicking the htmx booster link) and the call to history.pushState when the origin already has a history state (ie after two previous conventional link clicks) . My latest idea is to simply queue the missing URL for the next interaction, and essentially replay the history so it has the correct sequence. I’ll try to get it working over next few days but I’d very much welcome your input if my idea fails.
*to insert the missing history immediately on next interaction. Logically that could be a click on another htmx boosted link, but what if the user clicked another conventional link instead? So maybe any interaction should do it, like an element focus or scroll. I’ll experiment with a few things and see what happens.
m
OK
this is literally the hardest part of htmx, I really appreciate you taking a look at it
and I'm happy to jump on a video conf and help
h
So my idea failed. Safari is in fact creating a new entry in the history stack (I checked by compared history.length before and after a push) - it's just skipping it the entry when the user clicks back. But, I may have found out why: the title parameter of pushState is set to an empty string. Only Safari actualu uses this parameter. I think in certain circumstances (the 500ms since user interaction?) Safari will skip a history entry that has an empty title! I guess htmx could use the page title when it does a pushState or replaceState. I'm not entirely sure this is the full solution but I'll keep on experimenting.
Just to follow up, I think I've cracked it with an acceptable workaround. The problem was definitely the duration between the user click and the call to history.pushState being more than >500ms. Luckily, history.replaceState works fine, presumably because it doesn't create a history entry. From reading around browser vendors have added 'interventions' to the history API to prevent back-button abuse, and the latest Safari would appear to be the most sensitive. My solution is to send a pushState early (when appropriate), without waiting for the ajax response, so the history entry is reliably inserted. The response handler can then use replaceState instead of a push to update the final url. I was actually surprised to find it worked right away on my (very complex) app. I've also added a replaceState on initial page load and removed the replaceState in the
saveCurrentPageToHistory
function since it's not needed. I think you'll need to look closely at this and see if this functionality ("pushing early") is going to need to be hidden behind a config option or some other approach. I'll try to get the code in a sensible state and add it to the github issue over the next week. I've been working with 1.8.0 so I'll need to try it on your latest release too.
@mysterious-toddler-20573 I made a PR for this, not ready to merge yet but please review and let me know what you think about this approach. Many thanks! https://github.com/bigskysoftware/htmx/pull/1087
m
Absolute king! 🤴
at my computer, taking a look at the change now
awesome change. I am going to take some time on this one (the history API is really, really crappy) and think about the best cut point, but I think you've handled things very well
crazy bug, thank you for staying with it!
if you are interested in being part of the htmx team let me know and I'll give you triage access to the project based on this work
h
Wow, that would be an honour! Thank you. I’m planning to use htmx on a lot of projects so would be happy to contribute if I can.
3 Views